/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "网格.h"

#include <三角形.h>
#include <几何图形/图形相交.h>
#include <ppl.h>
#include <any>


#include "core/shader_ray.h"
#include "core/空间划分/球形八叉树.h"
#include "core/文件块.h"

#include "数学/数学.h"
#include "面/面.h"

#include "底层绘图/底层绘图框架.h"
#include "底层绘图/intern/Vulkan/线管/线管.h"
#include "底层绘图/intern/Vulkan/线管/着色器.h"
#include "底层绘图/intern/Vulkan/Vulkan框架.h"

#include "core/几何计算/凸包计算.h"
#include "core/几何计算/相交.h"


using namespace std;



static void on_mesh绘制参数设置(S_Mesh* me, const S_GPU内存块* 物体参数[2], uint32 多维子元素) {
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->MeshPropOffset = me->m_网格元素变换属性.m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->MatrixOffset = 物体参数[0]->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->ColorPropOffset = 物体参数[1]->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->DrawType = me->m_片源着色模式;

	uint32 绘制数量 = 0;
	uint32 fo = 0;
	if (me->m_元素->m_多维元素数量) {
		fo = me->m_元素->m_元素区间[me->m_多维材质槽[多维子元素].m_区间槽索引].z;
		((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->ElementOffset = fo;

		绘制数量 = me->m_元素->m_元素区间[me->m_多维材质槽[多维子元素].m_区间槽索引].y / 3;
	}
	else {
		((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->ElementOffset = fo;
	}

	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_AdjacencyID = (me->m_邻接面索引)->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_Normal = (me->m_面法线)->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_Center = (me->m_面中心)->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face = (me->m_面)->m_Mem.m_偏移;

	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->VertexOffset = (me->m_顶点)->m_Mem.m_偏移;
	
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BoneNum = (me->m_顶点骨骼属性)->m_Mem.m_数量;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonesOffset = (me->m_顶点骨骼属性)->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BoneWeigetOffset = (me->m_骨骼权重映射)->m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_MeshAttr = me->m_自定义属性索引->m_Mem.m_偏移;
	
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_MaterialAtt = me->m_多维材质槽[多维子元素].m_Material->m_材质自定义属性索引.m_Mem.m_偏移;
	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->ObMesh_Offset = me->m_网格属性->m_Mem.m_偏移;

	
	auto& attr = *me->m_面自定义属性区间偏移;
	for (auto& e : attr) {
		assert( (e.second.m_Mem.m_偏移 + fo + 绘制数量) <= e.second.m_Buf->m_Size );
	}
}



void f_mesh_切换顶点类型(S_Mesh* 目标, uint32 flags, uint32 num) {
	if (*目标->m_顶点配置Flags != flags) {
		f_bm_erase(*目标->m_顶点);

		switch (flags) {
			case E_顶点标志位::e_顶点坐标:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点v, num);
				break;
			case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点颜色:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点vc, num);
				break;
			case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点vn, num);
				break;
			case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线 | E_顶点标志位::e_顶点UV:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点vnt, num);
				break;
			case E_顶点标志位::e_空间曲线:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点curve, num);
				break;
			case E_顶点标志位::e_AABB:
				(*目标->m_顶点) = f_bm_alloc(f_buf_getGlobal().g_顶点Aabb, num);
				break;
		}
		(*目标->m_顶点配置Flags) = flags;
	}
	else {
		f_bm_resize(*目标->m_顶点, num);
	}
}


class C_顶点列队拷贝 : public C_缓存列队数据 {
	const std::vector<S_VNTC> m_数据源;
public:
	C_顶点列队拷贝(S_GPU内存块* 拷贝目标, const std::vector<S_VNTC>& vert) : m_数据源(std::move(vert)) {
		m_拷贝目标 = 拷贝目标;
	}

	S_GPU偏移大小 f_分配空间() {
		f_bm_resize(*m_拷贝目标, m_数据源.size());
		return m_拷贝目标->m_Mem;
	}

	void f_拷贝到GPU() {
		f_bm_fill(*m_拷贝目标, (uint8*)m_数据源.data(), m_数据源.size());
	}
};

template<typename T>
class C_网格索引列队拷贝 : public C_缓存列队数据 {
	const std::vector<T>	m_数据源;
	uint32					m_元素分量数量;
public:
	C_网格索引列队拷贝(S_GPU内存块* 拷贝目标, const std::vector<T>& vert) : m_数据源(std::move(vert)) {
		m_拷贝目标 = 拷贝目标;
		m_元素分量数量 = sizeof(T) / 拷贝目标->m_Buf->m_Offset;
	}

	S_GPU偏移大小 f_分配空间() {
		f_bm_resize(*m_拷贝目标, m_数据源.size() * m_元素分量数量);
		return m_拷贝目标->m_Mem;
	}

	void f_拷贝到GPU() {
		f_bm_fill(*m_拷贝目标, (uint8*)m_数据源.data(), m_数据源.size() * m_元素分量数量);
	}
};





S_Mesh操作::S_Mesh操作(S_Surface * s) :m_Mesh(s) {	
}
void S_Mesh操作::f_重置网格(S_Surface * s) {
}
void S_Mesh操作::f_Add(const S_Mesh操作 * mesh, const Mat44f * mat) {	
}
void S_Mesh操作::f_fill网格(const vector<vec3> xyz, const vector<vec3> normal, const vector<uvec4_8> color, const vector<uint32> index, const vector<vec2> texcoord, uint8 纹理坐标层数){
	void* ctx = 0;
	switch (f_get后端框架名称()) {
	case E_绘图API::E_DirectX12:
		ctx = f_get环境();
		break;
	default:
		break;
	} ;
}
void S_Mesh操作::f_add顶点(const vec3& xyz, const vec3& normal, const uvec4_8& color, const vec2* texcoord, uint8 纹理坐标层数){
}
void S_Mesh操作::f_add三角形(const ivec3 & index){
}
uint32 S_Mesh操作::f_get顶点数量() {
	return 0;
}
const vec3* S_Mesh操作::f_get顶点() {
	return 0;
}
vec3* S_Mesh操作::f_Map顶点() {
	return 0;
}
void S_Mesh操作::f_UnMap_顶点() {
}
uint32 S_Mesh操作::f_get索引数量() {
	return 0;
}
const uint32* S_Mesh操作::f_get索引() {
	return 0;
}
uint32* S_Mesh操作::f_Map索引() {
	return 0;
}
void S_Mesh操作::f_UnMap_索引() {
}
void S_Mesh_CUDA::f_AddMesh(const S_Mesh& m) {
}
void S_Mesh_CUDA::f_get顶点(S_结构指针 data) { 
	std::vector<vec3>& v = *((std::vector<vec3>*)data);

	uint32 num = m_positions.size();
	v.resize(num);

	auto* p = m_positions.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}
void S_Mesh_CUDA::f_get法线(S_结构指针 data) { 
	std::vector<vec3>& v = *((std::vector<vec3>*)data);

	uint32 num = m_normals.size();
	v.resize(num);

	auto* p = m_normals.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}
void S_Mesh_CUDA::f_get索引(S_结构指针 data) { 
	std::vector<uint32>& v = *((std::vector<uint32>*)data);

	uint32 num = m_indices.size();
	v.resize(num);

	auto* p = m_indices.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = p[i];
	});
}
void S_Mesh_CUDA::f_fill顶点(const std::vector<vec3>& xyz) {
	uint32 num = xyz.size();
	m_positions.resize(num);

	auto* p = xyz.data();
	auto* r = m_positions.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}
void S_Mesh_CUDA::f_fill法线(const std::vector<vec3>& normal) {
	uint32 num = normal.size();
	m_normals.resize(num);

	auto* p = normal.data();
	auto* r = m_normals.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}
void S_Mesh_CUDA::f_fill索引(const std::vector<uint32>& index) {
	uint32 num = index.size();
	m_indices.resize(num);

	auto* p = index.data();
	auto* r = m_indices.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = p[i];
	});
}

void S_Mesh_CUDA::f_fill颜色(const std::vector<uvec4_8>& color) {
	uint32 num = color.size();
	m_colours.resize(num);

	auto* p = color.data();
	auto* r = m_colours.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { float32(p[i].x / 255), float32(p[i].y / 255), float32(p[i].z / 255), float32(p[i].w / 255) };
	});
}

void S_Mesh_CUDA::f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层) {
}

void S_Mesh_CUDA::f_fill顶点(const vec3* xyz, uint32 num) {
}

void S_Mesh_CUDA::f_fill法线(const vec3* normal, uint32 num) {
}

void S_Mesh_CUDA::f_fillUV(const vec2* index, uint32 num) {

}
void S_Mesh_CUDA::f_DuplicateVertex(uint32_t i){
	assert(m_positions.size() > i);
	m_positions.push_back(m_positions[i]);

	if (m_normals.size() > i)
		m_normals.push_back(m_normals[i]);

	if (m_colours.size() > i)
		m_colours.push_back(m_colours[i]);

	if (m_texcoords[0].size() > i)
		m_texcoords[0].push_back(m_texcoords[0][i]);

	if (m_texcoords[1].size() > i)
		m_texcoords[1].push_back(m_texcoords[1][i]);
}
void S_Mesh_CUDA::f_CalculateNormals(){
}
void S_Mesh_CUDA::f_Normalize(float32 s) {
}
void S_Mesh_CUDA::f_getBounds(Vec3 & outMinExtents, Vec3 & outMaxExtents) const {
	Point3 minExtents(FLT_MAX);
	Point3 maxExtents(-FLT_MAX);

	for (uint32_t i = 0; i < m_positions.size(); ++i) {
		const Point3& a = m_positions[i];

		minExtents = Min(a, minExtents);
		maxExtents = Max(a, maxExtents);
	}
	outMinExtents = Vec3(minExtents);
	outMaxExtents = Vec3(maxExtents);
}








S_VKMesh板载缓存::S_VKMesh板载缓存(S_设备环境& ctx) : S_VKMesh板载缓存(ctx, nullptr, false, false, false, false, false, false) {
	
}

S_VKMesh板载缓存::S_VKMesh板载缓存(S_VKMesh板载缓存* p) : S_VKMesh板载缓存(m_Ctx, p, true, true, true, true, false) {
	
}

S_VKMesh板载缓存::S_VKMesh板载缓存(S_设备环境& ctx,
									S_VKMesh板载缓存* 引用网格
									, bool 关联顶点
									, bool 关联索引
									, bool 关联UV
									, bool 关联颜色
									, bool 关联权重
									, bool 关联属性
									)
	
{
	m_Ctx = ctx;

	m_关联顶点 = (关联顶点);
	m_关联索引 = (关联索引);
	m_关联权重 = (关联权重);
	m_关联颜色 = (关联颜色);
	m_关联UV = (关联UV);
	m_自定义属性链接 = 关联属性;

	m_Tye = E_网格数据枚举::e_Mesh_Vulkan;
	m_VertNum = 0;
	m_间接 = 0;

	if (引用网格) {
		m_Ctx = 引用网格->m_Ctx;
		m_Color = 引用网格->m_Color;
	}


	if (m_关联顶点) {
		m_顶点 = 引用网格->m_顶点;
		m_顶点配置Flags = 引用网格->m_顶点配置Flags;
		
		m_包围盒 = 引用网格->m_包围盒;
		m_Bound = 引用网格->m_Bound;

		m_点自定义属性区间偏移 = 引用网格->m_点自定义属性区间偏移;
	}
	else {
		m_顶点 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_顶点) = f_bm_alloc(m_Ctx.m_几何图形->m_3DGPU缓存_顶点, 0);

		m_顶点配置Flags = (uint32*)malloc(sizeof(uint32));
		(*m_顶点配置Flags) = 0;

		m_Bound = (S_Bounding*)malloc(sizeof(S_Bounding));
		m_包围盒 = (S_Cube*)malloc(sizeof(S_Cube));
		
		m_包围盒->pos = {};
		m_包围盒->size = { {}, {} };
		m_Bound->min = {};
		m_Bound->max = {};

		m_点自定义属性区间偏移 = new std::map<std::u16string, S_GPU内存块>();
	}

	if (m_关联权重) {
		m_顶点骨骼属性 = 引用网格->m_顶点骨骼属性;
		m_骨骼权重映射 = 引用网格->m_骨骼权重映射;
	}
	else {
		m_顶点骨骼属性 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_顶点骨骼属性) = f_bm_alloc(f_buf_getGlobal().g_骨骼属性, 0);

		m_骨骼权重映射 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_骨骼权重映射) = f_bm_alloc(f_buf_getGlobal().g_骨骼权重, 0);

	}
	


	if (m_关联索引) {
		m_索引 = 引用网格->m_索引;
		m_材质槽ID = 引用网格->m_材质槽ID;

		m_邻接面索引 = 引用网格->m_邻接面索引;
		m_面法线 = 引用网格->m_面法线;
		m_面中心 = 引用网格->m_面中心;

		m_面 = 引用网格->m_面;

		m_底层光追加速结构 = 引用网格->m_底层光追加速结构;
		
		
		m_网格属性 = 引用网格->m_网格属性;
		m_光追网格ID = 引用网格->m_光追网格ID;

		m_元素 = 引用网格->m_元素;

		m_面自定义属性区间偏移 = 引用网格->m_面自定义属性区间偏移;
	}
	else {
		m_索引 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_索引) = f_bm_alloc(m_Ctx.m_几何图形->m_3DGPU缓存_索引, 0);
		
		m_材质槽ID = (S_UI32Array*)f_core_array_new(1, sizeof(uint32));
		m_材质槽ID->ptr_userData[0] = 0;

		m_邻接面索引 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_邻接面索引) = f_bm_alloc(f_buf_getGlobal().g_邻接面索引, 0);
		m_面法线 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_面法线) = f_bm_alloc(f_buf_getGlobal().g_面法线, 0);
		m_面中心 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_面中心) = f_bm_alloc(f_buf_getGlobal().g_面中心, 0);
		
		m_面 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_面) = f_bm_alloc(f_buf_getGlobal().g_面, 0);

		//m_面属性 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		//(*m_面属性) = f_bm_alloc(f_buf_getGlobal().g_面, 0);


		m_元素 = (S_网格元素*)calloc(1, sizeof(S_网格元素));


		m_网格属性 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_网格属性) = f_bm_alloc(f_buf_getGlobal().m_场景物体网格属性, 1);


		
		m_面自定义属性区间偏移 = new std::map<std::u16string, S_GPU内存块>();
	}


	if (m_关联UV) {
		m_UV = 引用网格->m_UV;
		m_UV索引 = 引用网格->m_UV索引;
	}
	else {
		m_UV = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_UV) = f_bm_alloc(f_buf_getGlobal().g_UV坐标, 0);

		m_UV索引 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_UV索引) = f_bm_alloc(f_buf_getGlobal().g_UV索引, 0);
	}


	if (m_关联颜色) {
		m_颜色 = 引用网格->m_颜色;
	}
	else {
		m_颜色 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
		(*m_颜色) = f_bm_alloc(f_buf_getGlobal().g_颜色, 0);
	}


	//m_网格元素变换属性 = f_bm_alloc(f_buf_getGlobal().g_网格变换属性, 1);
	//f_buf_网格元素变换属性_at(m_网格元素变换属性) = f_init_MeshTranform();



	//if (m_自定义属性链接) {
	//	m_自定义属性索引 = 引用网格->m_自定义属性索引;
	//}
	//else {
	//	m_自定义属性索引 = (S_GPU内存块*)malloc(sizeof(S_GPU内存块));
	//	(*m_自定义属性索引) = f_bm_alloc(f_buf_getGlobal().g_自定义属性索引, DEF_网格自定义属性槽数量 * DEF_网格自定义属性槽数量);
	//	f_buf_属性索引_at(*m_自定义属性索引) = {};
	//}
	

	

	m_光追加速结构 = 0;
	mf_绘制参数设置 = on_mesh绘制参数设置;

	m_更新光追加速结构 = true;
}

S_VKMesh板载缓存::S_VKMesh板载缓存() {
	m_Ctx = {};
	m_VertNum = 0;

	if (m_间接) {
		f_bm_erase(*m_间接);
	}

	m_光追加速结构 = 0;

	m_关联顶点 = true;
	m_关联索引 = true;
	m_关联UV = true;

	m_是否链接 = true;
}

S_VKMesh板载缓存::~S_VKMesh板载缓存() {
	if (m_是否链接) {

	}
	else {
	
		if (!m_关联顶点) {
			f_bm_erase(*m_顶点);
			free(m_顶点);
			free(m_顶点配置Flags);

			delete m_点自定义属性区间偏移;
		}

		if (!m_关联索引) {
			f_bm_erase(*m_索引);
			free(m_索引);

			f_bm_erase(*m_邻接面索引);
			free(m_邻接面索引);
			f_bm_erase(*m_面法线);
			free(m_面法线);
			f_bm_erase(*m_面中心);
			free(m_面中心);

			f_bm_erase(*m_面);
			free(m_面);

			if (m_底层光追加速结构) {
				f_bm_erase(*m_底层光追加速结构);
				free(m_底层光追加速结构);
			}

			f_core_array_free((S_Array*)m_材质槽ID);
			f_me_free多维元素槽(this);

			delete m_面自定义属性区间偏移;
		}

		if (!m_关联UV) {
			f_bm_erase(*m_UV索引);
			f_bm_erase(*m_UV);

			free(m_UV索引);
			free(m_UV);
		}

		//if (!m_自定义属性链接) {
		//	f_bm_erase(*m_自定义属性索引);
		//	free(m_自定义属性索引);
		//}
	}



	

	if (m_关联权重) {
		
	}
	else {
		f_bm_erase(*m_顶点骨骼属性);
		free(m_顶点骨骼属性);

		f_bm_erase(*m_骨骼权重映射);
		free(m_骨骼权重映射);
	}




	f_bm_erase(m_网格元素变换属性);
	if (m_绘制内存属性) free(m_绘制内存属性);


	if (m_间接) {
		f_bm_erase(*m_间接);
	}
	
}

void S_VKMesh板载缓存::f_拷贝实例(const S_Mesh* mesh) {
	const S_VKMesh板载缓存* p = dynamic_cast<const S_VKMesh板载缓存*>(mesh);

	m_Ctx     = p->m_Ctx;
	m_VertNum = p->m_VertNum;

	m_顶点 = p->m_顶点;
	m_颜色 = p->m_颜色;
	m_索引 = p->m_索引;
	m_间接 = p->m_间接;

	m_材质槽ID = p->m_材质槽ID;
	m_顶点骨骼属性 = p->m_顶点骨骼属性;
	m_骨骼权重映射 = p->m_骨骼权重映射;

	m_底层光追加速结构 = p->m_底层光追加速结构;
	

	m_自定义属性索引 = p->m_自定义属性索引;
	m_自定义属性链接 = true;
	
	m_包围盒 = p->m_包围盒;
	m_Bound = p->m_Bound;

	m_UV = p->m_UV;
	m_UV索引 = p->m_UV索引;

	//m_Material = p->m_Material;
	m_网格元素变换属性 = p->m_网格元素变换属性;


	m_关联顶点 = true;
	m_关联索引 = true;
	m_关联UV = true;
}

void S_VKMesh板载缓存::f_fill顶点(const vec3* xyz, uint32 num) {
	if (!num) {
		f_bm_resize(*m_顶点, 0);
		return;
	}

	
	switch (*m_顶点配置Flags) {
		case 0:
		case E_顶点组合标志::e_坐标: {
			f_bm_resize(*m_顶点, num);
			vec3* v = f_buf_Vec3_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				v[i] = xyz[i];
			};
			break;
		}
	
		case E_顶点组合标志::e_坐标_法线: {
			f_bm_resize(*m_顶点, num);
			S_VN* vn = f_buf_VN_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				vn[i].vert = xyz[i];
			};
			break;
		}
	
		case E_顶点组合标志::e_坐标_颜色: {
			f_bm_resize(*m_顶点, num);
			S_VC* vc = f_buf_VC_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				vc[i].vert = xyz[i];
			};
			break;
		}

		case E_顶点组合标志::e_坐标_法线_UV: {
			f_bm_resize(*m_顶点, num);
			S_VNT1* vnt = f_buf_VNT_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				vnt[i].vert = xyz[i];
			};
			break;
		}
	}

	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

void S_VKMesh板载缓存::f_fill法线(const vec3* normal, uint32 num) {
	switch (*m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标_法线: {
		f_bm_resize(*m_顶点, num);
		S_VN* data = f_buf_VN_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].normal = normal[i];
		};
	}
	break;

	case E_顶点组合标志::e_坐标_法线_UV: {
		f_bm_resize(*m_顶点, num);
		S_VNT1* data = f_buf_VNT_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].normal = normal[i];
		};
	}
	break;

	default:
		break;
	}

	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

void S_VKMesh板载缓存::f_fillUV(const vec2* uv, uint32 num, uint8 纹理层) {
	
	switch (*m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
		
			f_bm_resize(*m_顶点, num);
			S_VNT1* data = f_buf_VNT_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				data[i].UV = uv[i];
			};
			break;
		}
	}

	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

void S_VKMesh板载缓存::f_fill颜色(const std::vector<S_RGBA8UI>& c) {
	uint32 num = c.size();
	
	auto* p = c.data();
	switch (*m_顶点配置Flags){
		case E_顶点组合标志::e_坐标_颜色: {
			f_bm_resize(*m_顶点, num);
			S_VC* data = f_buf_VC_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				data[i].color = f_PackData4X8(p[i]);
			};
			break;
		}
	}

	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

void S_VKMesh板载缓存::f_fillUV(const std::vector<vec2>& uv1, uint8 纹理层) {
}

void S_VKMesh板载缓存::f_fill权重(const float32* w, uint32 num) {
	//m_顶点配置Flags |= E_顶点标志位::e_顶点权重;
	//f_buf_fill板载缓存(m_蒙皮权重, w, num);
}

void S_VKMesh板载缓存::f_fill骨骼ID(const uint32* bid, uint32 num) {
	//m_顶点配置Flags |= E_顶点标志位::e_顶点权重;
	//f_buf_fill板载缓存(m_顶点对应骨骼ID, bid, num);
}


void S_VKMesh板载缓存::f_填充顶点数据(const std::vector<S_VN>& data) {
	*m_顶点配置Flags |= E_顶点标志位::e_顶点法线;
	f_bm_erase(*m_顶点);

	*m_顶点 = f_bm_alloc(f_buf_getGlobal().g_顶点vn, data.size());
	f_gbuf_fill(*m_顶点, data.data(), 0, data.size());
	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

void S_VKMesh板载缓存::f_填充顶点数据(const std::vector<S_VC>& data) {
	*m_顶点配置Flags |= E_顶点标志位::e_顶点颜色;
	if(data.size()) {
		f_bm_erase(*m_顶点);
		*m_顶点 = f_bm_alloc(f_buf_getGlobal().g_顶点vc, data.size());

		f_gbuf_fill(*m_顶点, data.data(), 0, data.size());
	}
	else f_Clear();
	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
}

uint32 S_VKMesh板载缓存::f_填充顶点数据(uint16 bitSize, uint64 num, void* data) {
	if(m_顶点->m_Buf) f_bm_erase(*m_顶点);
	uint32 sid = 0;

	f_mesh_切换顶点类型(this, *m_顶点配置Flags, num);
	if(num) {
		sid = m_顶点->m_Mem.m_偏移;
		f_gbuf_fill(*m_顶点, data, 0, num);
	}
	else {
		f_Clear();
	}
	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
	return sid;
}

uint32 S_VKMesh板载缓存::f_填充顶点数据(void* data, uint64 num, uint32 顶点配置) {
	if (m_顶点->m_Buf) f_bm_erase(*m_顶点);
	uint32 sid = 0;

	if (顶点配置 != *m_顶点配置Flags) {
		f_mesh_切换顶点类型(this, 顶点配置, num);
	}
	
	if (num) {
		sid = m_顶点->m_Mem.m_偏移;
		f_gbuf_fill(*m_顶点, data, 0, num);
	}
	else {
		f_Clear();
	}
	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;
	return sid;
}

uint32 S_VKMesh板载缓存::f_填充索引数据(uint16 bitSize, uint64 num, void* data) {
	
	bitSize = bitSize / sizeof(uint32);
	assert(bitSize);
	//f_bm_resize(*m_索引, num * bitSize);
	f_bm_fill(*m_索引, data, num * bitSize);
	//f_gbuf_fill(*m_索引, data, 0, num);
	
	

	/*switch (bitSize) {
		case 4:
			f_bm_resize(*m_面, num / 3);
			break;
		case 8:
			f_bm_resize(*m_面, num / 2);
			num *= 2;
			break;
		case 12:
			f_bm_resize(*m_面, num);

			num *= 3;
			break;
		case 16:
			break;
		default:
			break;
	}
	if (m_面->m_Mem.m_数量) {
		m_面->m_Buf->m_分配块内存锁.lock();
		S_FaceElement* fe = f_buf_面元素_ptr(*m_面);
		for (uint32 i = 0; i < m_面->m_Mem.m_数量; ++i) {
			fe[i].MaterialID = 0;
			fe[i].MaterialSlot = 0;
			fe[i].FacesMooth = 0;
			fe[i].ObType = DEF_OBTYPE_Mesh;
		}
		m_面->m_Buf->m_分配块内存锁.unlock();
	}
	
	m_更新光追加速结构 = true;
	m_光追图元更新偏移 = 0;
	m_光追结构更新偏移 = 0;*/
	return 0;
}

uint32 S_VKMesh板载缓存::f_fillUV索引数据(uint16 bitSize, uint32 num, const void* data) {
	bitSize /= 4;
	f_gbuf_fill(*m_UV索引, data, 0, num * bitSize);
	return m_UV索引->m_Mem.m_偏移;
}

void S_VKMesh板载缓存::f_重置顶点数量(uint64 num) {
	f_bm_resize(*m_顶点, num);
}

void S_VKMesh板载缓存::f_Clear() {
	f_bm_resize(*m_顶点, 0);
}

void S_VKMesh板载缓存::f_Clear索引() {
	f_bm_erase(*m_索引);
}

void S_VKMesh板载缓存::f_get顶点(std::vector<vec3>& vert) const {
	uint32 num = m_顶点->m_Mem.m_数量;
	vert.resize(num);
	auto* data = vert.data();

	switch (*m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标: {
			vec3* xyz = f_buf_Vec3_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				data[i] = xyz[i];
			};

			break;
		}
		
		case E_顶点组合标志::e_坐标_UV: {
			break;
		}

		case E_顶点组合标志::e_坐标_权重: {
			break;
		}

		case E_顶点组合标志::e_坐标_法线: {
			S_VN* xyz = f_buf_VN_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				data[i] = xyz[i].vert;
			};

			break;
		}

		case E_顶点组合标志::e_坐标_法线_UV: {
			break;
		}

		case E_顶点组合标志::e_坐标_法线_UV_颜色: {
			break;
		}

		case E_顶点组合标志::e_坐标_颜色: {
			break;
		}
	}
}

void S_VKMesh板载缓存::f_get法线(std::vector<vec3>& normal) const {
	uint32 num = m_顶点->m_Mem.m_数量;
	normal.resize(num);

	auto* data = normal.data();

	switch (*m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标: {
		
			break;
		}

		case E_顶点组合标志::e_坐标_UV: {

			break;
		}

		case E_顶点组合标志::e_坐标_权重: {

			break;
		}

		case E_顶点组合标志::e_坐标_法线: {
			S_VN* xyz = f_buf_VN_ptr(*m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				data[i] = xyz[i].vert;
			};
			break;
		}

		case E_顶点组合标志::e_坐标_法线_UV: {

			break;
		}

		case E_顶点组合标志::e_坐标_法线_UV_颜色: {

			break;
		}

		case E_顶点组合标志::e_坐标_颜色: {

			break;
		}
	}
}

void S_VKMesh板载缓存::f_get索引(std::vector<uint32>& index) const {
	index.resize(m_索引->m_Mem.m_数量);
	memcpy(index.data(), f_buf_UI32_ptr(*m_索引), sizeof(uint32) * m_索引->m_Mem.m_数量);
}

void S_VKMesh板载缓存::f_get颜色(std::vector<vec4>& index) const {
}

E_序列map S_VKMesh板载缓存::f_map索引() {
	return { f_buf_UI32_ptr(*m_索引), m_索引->m_Mem.m_数量 };
}

uint32 S_VKMesh板载缓存::f_get顶点数量() {
	return m_顶点->m_Mem.m_数量;
}

uint32 S_VKMesh板载缓存::f_get索引数量() {
	if (m_索引) return m_索引->m_Mem.m_数量;
	return 0;
}

void S_VKMesh板载缓存::f_绘制(S_渲染参数& 渲染参数, uint32 多维子元素) {
	渲染参数.m_线宽 = m_线宽;
	
	渲染参数.m_顶点内存偏移 = m_顶点->m_Mem.m_偏移;
	渲染参数.m_顶点数量 = m_顶点->m_Mem.m_数量;
	
	S_着色线管* 线管;
	S_VK渲染环境* info = f_vk_get绘图环境(m_Ctx);

	switch (渲染参数.m_线管槽) {
		case E_管线槽::e_颜色渲染: {
			线管 = m_多维材质槽[多维子元素].m_Material->m_着色线管;
			break;
		}
		case E_管线槽::e_阴影渲染: {
			线管 = m_多维材质槽[多维子元素].m_Material->m_阴影着色线管;
			break;
		}
		case E_管线槽::e_环境渲染: {
			线管 = m_多维材质槽[多维子元素].m_Material->m_环境着色线管;
			break;
		}
		case E_管线槽::e_几何渲染: {
			线管 = m_多维材质槽[多维子元素].m_Material->m_几何着色线管;
			break;
		}
		default:
			线管 = m_多维材质槽[多维子元素].m_Material->m_着色线管;
			break;
	}
	

	if (m_绘制内存属性) {
		vkCmdPushConstants(info->m_命令缓存, 
							static_cast<S_Vk着色*>(线管->m_Shader)->m_线管布局,
							f_vk_get参数布局着色阶段(m_绘制属性绑定阶段),
							0, 
							m_绘制属性字节大小,
							m_绘制内存属性);
	}
	
	if (m_索引->m_Mem.m_数量) {
		S_索引渲染参数 索引参数;
		
		索引参数.m_索引 = m_索引->m_Buf;
		索引参数.m_实例数量 = 渲染参数.m_实例数量;
		
		assert(m_索引->m_Mem.m_数量);
		assert(m_绘制内存属性);
		
		f_Draw_索引三角形(m_Ctx, 线管, m_顶点->m_Buf, 索引参数, 渲染参数);
	}
	else if(m_顶点->m_Mem.m_数量) {
		if (m_间接) {
			渲染参数.m_间接 = m_间接;
			f_Draw_间接序列(m_Ctx, 线管, m_顶点->m_Buf, 渲染参数);
		}
		else {
			f_Draw_序列(m_Ctx, 线管, m_顶点->m_Buf, 渲染参数);
		}
	}
}



void f_mesh_fill顶点数据(S_Mesh* mesh, const std::vector<vec3>& 点, const std::vector<vec3>& 法线, const std::vector<vec2>& UV) {
	uint32 num = DEF_Max(DEF_Max(点.size(), 法线.size()), UV.size());

	f_mesh_切换顶点类型(mesh, E_顶点组合标志::e_坐标_法线_UV, num);

	bool 顶点多例 = 点.size() >= num;
	bool 法线多例 = 法线.size() >= num;
	bool UV多例 = UV.size() >= num;

	auto vert = f_buf_VNT_ptr(*mesh->m_顶点);
	for (uint32 i = 0; i < num; ++i) {
		vert[i].vert = 顶点多例 ? 点[i] : 点[0];
		vert[i].normal = 法线多例 ? 法线[i] : 法线[0];
		vert[i].UV = UV多例 ? UV[i] : UV[0];

	}
	mesh->m_更新光追加速结构 = true;
}

//void f_surface_fill顶点数据(S_Mesh* mesh, const S_板载缓存* 点, const S_板载缓存* 法线, const S_板载缓存* UV) {
//	uint32 num = DEF_Max(DEF_Max(点->m_Size, 法线->m_Size), UV->m_Size);
//	f_mesh_切换顶点类型(mesh, E_顶点组合标志::e_坐标_法线_UV, num);
//
//	bool 顶点多例 = 点->m_Size >= num;
//	bool 法线多例 = 法线->m_Size >= num;
//	bool UV多例 = UV->m_Size >= num;
//
//	auto vert = f_buf_VNT_ptr(*mesh->m_顶点);
//	for (uint32 i = 0; i < num; ++i) {
//		vert[i].vert = 顶点多例 ? ((vec3*)点->m_mappedPtr)[i] : ((vec3*)点->m_mappedPtr)[0];
//		vert[i].normal = 法线多例 ? ((vec3*)法线->m_mappedPtr)[i] : ((vec3*)法线->m_mappedPtr)[0];
//		vert[i].UV = UV多例 ? ((vec2*)UV->m_mappedPtr)[i] : ((vec2*)UV->m_mappedPtr)[0];
//	}
//}

void f_mesh_fill顶点数据(S_Mesh* mesh, const S_GPU内存块& 点, const S_GPU内存块& 法线, const S_GPU内存块& UV) {
	uint32 num = DEF_Max(DEF_Max(点.m_Mem.m_数量, 法线.m_Mem.m_数量), UV.m_Mem.m_数量);
	f_mesh_切换顶点类型(mesh, E_顶点组合标志::e_坐标_法线_UV, num);
	if(!num) return;

	bool 顶点多例 = 点.m_Mem.m_数量 >= num;
	bool 法线多例 = 法线.m_Mem.m_数量 >= num;
	bool UV多例 = UV.m_Mem.m_数量 >= num;

	auto vert = f_buf_VNT_ptr(*mesh->m_顶点);
	auto v = f_buf_Vec3_ptr(点);
	auto n = f_buf_Vec3_ptr(法线);
	auto uv = f_buf_Vec2_ptr(UV);

	for (uint32 i = 0; i < num; ++i) {
		vert[i].vert	= 顶点多例 ? v[i] : v[0];
		vert[i].normal	= 法线多例 ? n[i] : n[0];
		vert[i].UV		= UV多例 ? uv[i] : uv[0];
	}

	mesh->m_更新光追加速结构 = true;
}




void S_Mesh_CPU::f_AddMesh(const S_Mesh& m) {
}
void S_Mesh_CPU::f_fill顶点(const std::vector<vec3>& xyz) {
}
void S_Mesh_CPU::f_fill法线(const std::vector<vec3>& normal) {
}
void S_Mesh_CPU::f_fill索引(const std::vector<uint32>& index) {
}
void S_Mesh_CPU::f_fill颜色(const std::vector<uvec4_8>& color) {
}
void S_Mesh_CPU::f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层) {
}
void S_Mesh_CPU::f_fill顶点(const vec3* xyz, uint32 num) {
}
void S_Mesh_CPU::f_fill法线(const vec3* normal, uint32 num) {
}
void S_Mesh_CPU::f_fillUV(const vec2* index, uint32 num) {
}

void S_Mesh_CPU::f_填充顶点数据(const std::vector<S_VN>& data) {
	uint32 num = data.size();
	auto* vn = data.data();

	m_positions.resize(num*2);
	for (uint32 i = 0; i < num; ++i) {
		m_positions[i*2] = vn[i].vert;
		m_positions[i*2+1] = vn[i].normal;
	}
}

void S_Mesh_CPU::f_填充顶点数据(const std::vector<S_VC>& data) {

}

uint32 S_Mesh_CPU::f_填充顶点数据(uint16 bitSize, uint64 num, void* data) {
	m_positions.resize(num);
	memcpy(m_positions.data(), data, num * bitSize);
	return 0;
}

uint32 S_Mesh_CPU::f_填充索引数据(uint16 bitSize, uint64 num, void* data) {
	switch (bitSize)
	{
		case sizeof(uint32) :
			m_indices.resize(num);
			break;

			case sizeof(uvec3):
				m_indices.resize(num * 3);
				break;
	default:
		break;
	}
	
	memcpy(m_indices.data(), data, num * bitSize);
	return 0;
}

void S_Mesh_CPU::f_get顶点(std::vector<vec3>& vert) const {
	vert = m_positions;
}

void S_Mesh_CPU::f_get法线(std::vector<vec3>& normal) const {
	normal = m_normals;
}

void S_Mesh_CPU::f_get索引(std::vector<uint32>& index) const {
	index = m_indices;
}

void S_Mesh_CPU::f_get颜色(std::vector<vec4>& index) const {

}

void S_Mesh_CPU::f_Clear() {
	m_positions.clear();
}

void S_Mesh_CPU::f_Clear索引() {
	m_indices.clear();
}

void S_Mesh_CPU::f_getBounds(Vec3& minExtents, Vec3& maxExtents) const {
}




void f_me_fill顶点(S_Mesh* me, const std::vector<S_VNTC>& vert) {
	if (me->m_顶点->m_Buf->m_流) {
		auto data = std::make_unique<C_顶点列队拷贝>(me->m_顶点, vert);
		f_bm_添加更新缓存列队(std::move(data));
	}
	else {
		f_bm_fill(*me->m_顶点, vert.data(), vert.size());
	}
}

void f_me_fill索引(S_Mesh* me, const std::vector<uint32>& data) {
	if (me->m_索引->m_Buf->m_流) {
		f_bm_添加更新缓存列队(std::move(std::make_unique<C_网格索引列队拷贝<uint32>>(me->m_索引, data)));
	}
	else {
		if (data.size()) f_填充索引数据<uint32>(me, data);
		else me->f_Clear索引();
	}
}

void f_me_fill索引(S_Mesh* me, const std::vector<uvec2>& data) {
	if (me->m_索引->m_Buf->m_流) {
		f_bm_添加更新缓存列队(std::move(std::make_unique<C_网格索引列队拷贝<uvec2>>(me->m_索引, data)));
	}
	else {
		if (data.size()) me->f_填充索引数据(sizeof(uvec2), data.size(), (void*)data.data());
		else me->f_Clear索引();
	}
}

void f_me_fill索引(S_Mesh* me, const std::vector<uvec3>& data) {
	if (me->m_索引->m_Buf->m_流) {
		f_bm_添加更新缓存列队(std::move(std::make_unique<C_网格索引列队拷贝<uvec3>>(me->m_索引, data)));
	}
	else {
		if (data.size()) me->f_填充索引数据(sizeof(uvec3), data.size(), (void*)data.data());
		else me->f_Clear索引();
	}
}



//uint32 f_me_fill索引(S_Mesh* me, const std::vector<uint32>& index) {
//	f_bm_fill(*me->m_索引, index.data(), index.size());
//	return me->m_索引->m_Mem.m_偏移;
//}



//Inline vec3 f_surface_FaceNormal(const vec3& v0, const vec3& v1, const vec3& v2) {
//	vec3 e0 = (v1 - v0);
//	vec3 e1 = (v2 - v0);
//	return (cross(e0, e1));
//}

S_Vec3Array* f_surface_点(const S_Vec3Array* 点, const S_Vec3Array* loc) {
	S_Vec3Array* a = (S_Vec3Array*)f_core_array_new(点->count * loc->count, sizeof(vec3));

	for (uint32 i = 0; i < loc->count; ++i) {
		uint32 index = i * 点->count;
		for (uint32 k = 0; k < 点->count; ++k) {
			a->ptr_userData[index + k] = 点->ptr_userData[k] + loc->ptr_userData[i];
		}
	}

	return a;
}

void f_mesh_fill平面(S_Mesh* me, vec2 大小, uvec2 细分) {
	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	std::vector<uvec2> 边索引;

	f_graph_构建平面(大小, 细分, 顶点, 法线, UV, 索引, 边索引, true);

	std::vector<S_VNT1> vnData;
	f_surface_数组合并(vnData, 顶点, 法线, UV);

	//switch (方向) {
	//	case E_方向::e_左: {
	//		vnData *= f_graph_vec_build_quat({0,0,1}, M_角度转弧度(90));
	//		break;
	//	}
	//	case E_方向::e_右: {
	//		vnData *= f_graph_vec_build_quat({ 0,0,1 }, M_角度转弧度(-90));
	//		break;
	//	}
	//	case E_方向::e_上: {
	//		break;
	//	}
	//	case E_方向::e_下: {
	//		break;
	//	}
	//	case E_方向::e_Dir_前: {
	//		break;
	//	}
	//	case E_方向::e_Dir_后: {
	//		break;
	//	}
	//	default:
	//		break;
	//}

	f_mesh_fill顶点数据(me, vnData);
	f_me_fill索引(me, 索引);
	f_mesh_计算包围盒(me);
	f_surface_计算三角形边相邻面索引(me);
	f_mesh_set绘制内存属性(me, {});
}

void f_mesh_fill立方体(S_Mesh* me, vec3 大小, uvec3 细分) {
	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	f_graph_构建立方体(大小, 细分, 顶点, 法线, UV, 索引, true);

	std::vector<S_VNT1> vnData;
	f_surface_数组合并(vnData, 顶点, 法线, UV);

	f_mesh_fill顶点数据(me, vnData);
	f_me_fill索引(me, 索引);
	f_mesh_计算包围盒(me);
	f_surface_计算三角形边相邻面索引(me);
	f_mesh_set绘制内存属性(me, {});
}

void f_mesh_fill球体(S_Mesh* me, float32 大小, uvec2 细分) {
	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	f_graph_构建球体(细分.x, 细分.y, 大小, 顶点, 法线, UV, 索引, true);

	std::vector<S_VNT1> vnData;
	f_surface_数组合并(vnData, 顶点, 法线, UV);

	f_mesh_fill顶点数据(me, vnData);
	f_me_fill索引(me, 索引);
	f_mesh_计算包围盒(me);
	f_surface_计算三角形边相邻面索引(me);
	f_mesh_set绘制内存属性(me, {});
}

void f_mesh_fill圆柱体(S_Mesh* me, vec2 大小, uvec2 细分) {
	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	f_graph_构建圆柱体(大小, 细分, 顶点, 法线, UV, 索引, true);

	std::vector<S_VNT1> vnData;
	f_surface_数组合并(vnData, 顶点, 法线);

	f_mesh_fill顶点数据(me, vnData);
	f_me_fill索引(me, 索引);
	f_mesh_计算包围盒(me);
	f_surface_计算三角形边相邻面索引(me);
	f_mesh_set绘制内存属性(me, {});
}

void f_mesh_fillL板(S_Mesh* me, vec2 大小, float32 圆角半径, uint32 细分) {
	std::vector<vec2> 圆(细分);
	f_graph_计算圆坐标XZ(_Vec2(圆角半径), 圆角半径, 细分, 圆.data(), 90, 180);

	//vec2 scale = 大小;

	S_Vec3Array* vert = (S_Vec3Array*)f_core_array_new_type(细分 + 2, E_值类型::e_Type_Vec3_1D);

	vert->ptr_userData[0] = { -0.5f * 大小.x, max(大小.y, 圆角半径), 0.0 };
	for (uint32 i = 0; i < 细分; ++i) {
		vert->ptr_userData[i + 1] = _Vec3(-0.5f * 大小.x, (圆[i]));
	}
	vert->ptr_userData[细分 + 1] = { -0.5f * 大小.x, 0.0, max(大小.y, 圆角半径) };


	auto poly = f_surface_创建多边形();
	auto edgeA = f_surface_添加多边形顶点(poly, vert, nullptr);

	for (uint32 i = 0; i < 细分 + 2; ++i) {
		vert->ptr_userData[i].x = 大小.x * 0.5;
	}
	auto edgeB = f_surface_添加多边形顶点(poly, vert, nullptr);

	auto* 边A = f_surface_添加多边形边(poly, edgeA, E_线绘制模式::e_线_连续);
	auto* 边B = f_surface_添加多边形边(poly, edgeB, E_线绘制模式::e_线_连续);
	f_surface_多边形桥接(poly, *边A, *边B);



	
	uint32 num = poly->m_顶点.size();
	std::vector<S_VNT1> 顶点(num);
	for (uint32 i = 0; i < num; ++i) {
		顶点[i].vert = poly->m_顶点[i];
		顶点[i].normal = {};
		顶点[i].UV = {};
	}

	f_mesh_fill顶点数据(me, 顶点);
	f_mesh_多边形三角化(me, poly);
	f_surface_计算面平滑法线(me);
	f_mesh_计算包围盒(me);
	f_surface_材质面区间(me, f_g_预设材质().g_基本光照面材质);


	f_surface_销毁多边形(poly);
}

template<typename T>
void f_计算网格三角形法线(S_点距八叉树* t, T* p顶点, uvec3* p索引, int32 num) {
#pragma omp parallel for
	for (int32 i = 0; i < num; ++i) {
		std::vector<void*> 面索引_空间数据;

		f_空间划分_get位置子集数据(t, p顶点[i].vert, 面索引_空间数据);

		vec3 法线 = {};
		void** 面索引_空间数据_ptr = 面索引_空间数据.data();
		uint32 面索引_空间数据数量 = 面索引_空间数据.size();

		for (uint32 空间数据_i = 0; 空间数据_i < 面索引_空间数据数量; ++空间数据_i) {
			auto* 面索引组 = (*((std::vector<uint32>*)面索引_空间数据_ptr[空间数据_i])).data();
			uint32 面索数量 = (*((std::vector<uint32>*)面索引_空间数据_ptr[空间数据_i])).size();
			for (uint32 index = 0; index < 面索数量; ++index) {
				uvec3 trangle = p索引[面索引组[index]];
				if (trangle.x == i || trangle.y == i || trangle.z == i) {
					法线 += f_surface_FaceNormal(p顶点[trangle.x].vert, p顶点[trangle.y].vert, p顶点[trangle.z].vert);
				}
			}
		}

		p顶点[i].normal = vec_normalize(法线);
	}
}

void f_surface_计算三角形球体包围盒(S_Mesh* mesh, std::vector<S_Sphere>& 包围盒) {
	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);

	uint32 num = mesh->m_索引->m_Mem.m_数量 / 3;
	
	包围盒.resize(num);
	auto* bounds_ptr = 包围盒.data();


	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线 || *mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(vn[index.x].vert, vn[index.y].vert, vn[index.z].vert);
			bounds_ptr[i] = q;
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		
		S_VNT1* vn = f_buf_VNT_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(vn[index.x].vert, vn[index.y].vert, vn[index.z].vert);
			bounds_ptr[i] = q;
		}
	}
	else {
		vec3* p顶点 = f_buf_Vec3_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(p顶点[index.x], p顶点[index.y], p顶点[index.z]);
			bounds_ptr[i] = q;
		}
	}
}


void f_surface_计算面平滑法线(S_Mesh* mesh, S_点距八叉树* t) {
	std::vector<S_Sphere> 包围盒;

	f_surface_计算三角形球体包围盒(mesh, 包围盒);
	f_空间划分_从包围盒构建子集(t, 包围盒);

	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);
	uint32 num   = mesh->m_顶点->m_Mem.m_数量;
	

	switch (*mesh->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* vn = f_buf_VNT_ptr(*mesh->m_顶点);
			f_计算网格三角形法线(t, vn, p索引, num);
			break;
		}
		case E_顶点组合标志::e_坐标_法线: {
			S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
			f_计算网格三角形法线(t, vn, p索引, num);
			break;
		}
		default:
			break;
	}
}



std::vector<S_VNT1> f_mesh_顶点变换(const S_Mesh& me, const Mat44f& m) {
	uint32 num = me.m_顶点->m_Mem.m_数量;
	std::vector<S_VNT1> 新点(num);

	auto rot = f_mat44_to_33(m);

	switch (*me.m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* vn = f_buf_VNT_ptr(*me.m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				新点[i] = vn[i];
				新点[i].vert = m * vn[i].vert;
				新点[i].normal = normalize(rot * vn[i].normal);
			}
			break;
		}
		//case E_顶点组合标志::e_坐标_法线: {
		//	S_VN* vn = f_buf_VN_ptr(*me.m_顶点);
		//	f_计算网格三角形法线(t, vn, p索引, num);
		//	break;
		//}
		default:
			break;
	}
	return 新点;
}

std::vector<S_VNT1> f_mesh_STL_顶点(const S_Mesh& me) {
	uint32 num = me.m_顶点->m_Mem.m_数量;
	std::vector<S_VNT1> 新点(num);

	switch (*me.m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* vn = f_buf_VNT_ptr(*me.m_顶点);
			for (uint32 i = 0; i < num; ++i) {
				新点[i] = vn[i];
			}
			break;
		}
		default:
			break;
	}
	return 新点;
}
std::vector<uint32> f_mesh_STL_索引(const S_Mesh& me) {
	uint32 num = me.m_索引->m_Mem.m_数量;
	std::vector<uint32> 索引(num);

	uint32* index = f_buf_UI32_ptr(*me.m_索引);
	for (uint32 i = 0; i < num; ++i) {
		索引[i] = index[i];
	}
	return 索引;
}



S_面拾取 f_surface_射线面相交(S_Mesh* mesh, const Mat44f mat[2], const S_MeshTranformProp& 间接属性, const uvec2& Offset_num, const vec3& s, const vec3& dir) {
	auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;
	vec3 scale = {间接属性.m_XScale, 间接属性.m_YScale, 间接属性.m_ZScale};


	uint32 num = Offset_num.y / 3;
	S_面拾取 拾取信息 = {{}, 100000000, -1};
	vec3     相交坐标 = {};


	bool 是否相交 = false;
	int32 相交情况 = 0;
	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
		S_VN* vn = (S_VN*)顶点指针;
		
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;

			uint32 index = i*3 + Offset_num.x;
			v1 = mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
			v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
			v3 = mat[1] * (vn[index + 2].vert * 间接属性.m_Scale);

			v1 = mat[0] * v1;

			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交宽度) {
					拾取信息.相交宽度 = 距离;
					拾取信息.面索引 = i;
					
					是否相交 = true;
				}
			}
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		S_VNT1* vn = (S_VNT1*)顶点指针;
		
		//#pragma omp parallel for num_threads(线程数)
		for (int32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;

			uint32 index = i*3 + Offset_num.x;
			v1 = mat[0] * (vn[index    ].vert * 间接属性.m_Scale);
			v2 = mat[0] * (vn[index + 1].vert * 间接属性.m_Scale);
			v3 = mat[0] * (vn[index + 2].vert * 间接属性.m_Scale);


			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交宽度) {
					拾取信息.相交宽度 = 距离;
					拾取信息.面索引 = i;
					
					是否相交 = true;
				}
			}
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VC* vn = (S_VC*)顶点指针;

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3 = {间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove};
			v1 = v2 = v3;

			uint32 index = i*3 + Offset_num.x;
			switch (间接属性.m_TransformMode) {
			case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
				v1 += mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
				v2 += mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
				v3 += mat[1] * (vn[index + 2].vert * 间接属性.m_Scale);
				break;
			}

			default:
				v1 += (vn[index    ].vert * 间接属性.m_Scale);
				v2 += (vn[index + 1].vert * 间接属性.m_Scale);
				v3 += (vn[index + 2].vert * 间接属性.m_Scale);
				break;
			}

			v1 = mat[0] * v1;
			v2 = mat[0] * v2;
			v3 = mat[0] * v3;


			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交宽度) {
					拾取信息.相交宽度 = 距离;
					拾取信息.面索引 = i;
					
					是否相交 = true;
				}
			}
		}
	}
	else {
		vec3* v = (vec3*)顶点指针;

		for (uint32 i = 0; i < num; ++i) {
			uint32 index = i*3;
			vec3 v1 = mat[0] * (v[index    ] * 1);
			vec3 v2 = mat[0] * (v[index + 1] * 1);
			vec3 v3 = mat[0] * (v[index + 2] * 1);
			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交宽度) {
					拾取信息.相交宽度 = 距离;
					拾取信息.面索引 = i;
					
					是否相交 = true;
				}
			}
		}
	}

	return 拾取信息;
}


S_线拾取 f_surface_线段相交(S_Mesh* mesh, const Mat44f mat[2], const S_MeshTranformProp& 间接属性, const uvec2& Offset_num, vec3 s, const vec3& dir, float32 最小相交距离) {
	S_线拾取 拾取线 = { {}, 最小相交距离, 1000000000, -1 };
	uint32 num = Offset_num.y / 2;
	if (!num) return 拾取线;

	vec3 最近距离顶点 = {};

	auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;
	

	vec3 射线长度补偿 = dir * 最小相交距离;
	s -= 射线长度补偿;

	switch (*mesh->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			f_buf_VNT_ptr(*mesh->m_顶点);
			break;
		}
		case E_顶点组合标志::e_坐标_法线: {
			S_VN* vn = (S_VN*)(顶点指针);

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2 = { 间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove };
				v1 = v2;

				uint32 index = i * 2 + Offset_num.x;
				switch (间接属性.m_TransformMode) {
					case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
						v1 = mat[1] * (vn[index].vert * 间接属性.m_Scale);
						v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
						break;
					}

					default:
						v1 = (vn[index].vert * 间接属性.m_Scale);
						v2 = (vn[index + 1].vert * 间接属性.m_Scale);
						break;
				}
				v1 = mat[0] * v1;
				v2 = mat[0] * v2;




				vec3 相交点;
				float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离));
				if (两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}
			}

			拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);

			break;
		}

		case E_顶点组合标志::e_坐标_颜色: {
			S_VC* vn = (S_VC*)(顶点指针);
			//S_VC* vn = f_buf_VC_ptr(*mesh->m_顶点);

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2 = { 间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove };
				v1 = v2;

				uint32 index = i * 2 + Offset_num.x;

				switch (间接属性.m_TransformMode) {
					case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
						v1 = mat[1] * (vn[index].vert * 间接属性.m_Scale);
						v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
						break;
					}

					default:
						v1 = (vn[index].vert * 间接属性.m_Scale);
						v2 = (vn[index + 1].vert * 间接属性.m_Scale);
						break;
				}
				v1 = mat[0] * v1;
				v2 = mat[0] * v2;

				vec3 相交点;
				float32 两线段距离 = f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离);
				if (两线段距离 >= 0 && 两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}
			}

			拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);
			break;
		}
		default: {
			vec3* v = (vec3*)(顶点指针);
			//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);

			for (uint32 i = 0; i < num; ++i) {
				uint32 index = i * 2 + Offset_num.x;
				vec3 v1, v2 = { 间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove };
				v1 = v2;

				switch (间接属性.m_TransformMode) {
					case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
						v1 = mat[1] * (v[index] * 间接属性.m_Scale);
						v2 = mat[1] * (v[index + 1] * 间接属性.m_Scale);
						break;
					}

					default:
						v1 = (v[index] * 间接属性.m_Scale);
						v2 = (v[index + 1] * 间接属性.m_Scale);
						break;
				}
				v1 = mat[0] * v1;
				v2 = mat[0] * v2;

				vec3 相交点;
				float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离));
				if (两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}

			}

			拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);
			break;
		}
	}

	return 拾取线;
}

S_线拾取 f_surface_线段相交(S_Mesh* mesh, const Mat44f mat[2], const vec3& s, const vec3& dir, float32& 距离, uint32 实例) {
	S_线拾取 拾取线 = { {}, 距离, 10000000, -1 };

	vec3 最近距离顶点 = {};
	const auto& 元素变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 0);
	//const vec3 camPos = _Vec3(mat[2].m30, mat[2].m31, mat[2].m32);
	const vec3 camPos{};

	switch (*mesh->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			uint32 num = mesh->m_索引->m_Mem.m_数量 / 2;

			S_VNT1* 顶点 = f_buf_VNT_ptr(*mesh->m_顶点);
			uvec2* 索引 = (uvec2*)f_buf_UI32_ptr(*mesh->m_索引);
			

			auto viewInverseMat = f_mat44_to_33(mat[1]);
			

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;

				uvec2 index = 索引[i];
				v1 = 顶点[index.x].vert;
				v2 = 顶点[index.y].vert;

				f_lineMeshTranform(v1, 顶点[index.x].normal, 元素变换属性, mat[0], viewInverseMat, camPos);
				f_lineMeshTranform(v2, 顶点[index.y].normal, 元素变换属性, mat[0], viewInverseMat, camPos);
				
				vec3 相交点;
				float32 两线段距离 = f_graph_两线段距离(v1, v2, s, dir, 相交点);
				if (两线段距离 >= 0 && 两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					最近距离顶点 = 相交点;
				}
			}
			break;
		}

		case E_顶点组合标志::e_坐标_法线: {
			const auto& indirect = f_buf_Indirect_at(*mesh->m_间接, 实例);
			uint32 num = indirect.vertexCount / 2;
			if (!num) return 拾取线;

			S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;
				uint32 index = i * 2;
				v1 = mat[0] * vn[indirect.firstVertex + index].vert;
				v2 = mat[0] * vn[indirect.firstVertex + index + 1].vert;

				vec3 相交点;
				float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点));
				if (两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}
			}
		}

		case E_顶点组合标志::e_坐标_颜色: {
			const auto& indirect = f_buf_Indirect_at(*mesh->m_间接, 实例);
			uint32 num = indirect.vertexCount / 2;
			if (!num) return 拾取线;

			S_VC* vc = (S_VC*)(mesh->m_顶点->m_Buf->m_mappedPtr);

			mat4 ModelMat = *(mat4*)&mat;
			for (uint32 i = 0; i < num; ++i) {
				uint32 index = i * 2;

				vec3 v1 = vc[indirect.firstVertex + index].vert;
				vec3 v2 = vc[indirect.firstVertex + index + 1].vert;


				v1 = mat[0] * v1;
				v2 = mat[0] * v2;
			
				vec3 相交点;
				float32 两线段距离 = f_graph_两线段距离(v1, v2, s, dir, 相交点); 
				if (两线段距离 >= 0.0f && 两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}
			}
		}
		default: {
			const auto& indirect = f_buf_Indirect_at(*mesh->m_间接, 实例);
			uint32 num = indirect.vertexCount / 2;
			if (!num) return 拾取线;

			vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
		
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				index.x = i * 2;
				index.y = i * 2 + 1;
				vec3 v1 = mat[0] * v[index.x + indirect.firstVertex];
				vec3 v2 = mat[0] * v[index.y + indirect.firstVertex];


				vec3 相交点;
				float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点));
				if (两线段距离 < 拾取线.相交宽度) {
					拾取线.相交宽度 = 两线段距离;
					拾取线.线索引 = i;
					最近距离顶点 = 相交点;
				}

			}
		}
	}

	距离 = vec_len(最近距离顶点 - s);

	if (拾取线.线索引 >= 0) {
		拾取线.相交宽度 *= f_mesh_get网格元素绘制属性(mesh).m_DepthScale;
	}
	return 拾取线;
}

S_点拾取 f_surface_点相交(S_Mesh* me, const Mat44f mat[2], vec3 s, const vec3& dir, float32 最小相交距离) {
	S_点拾取 拾取点 = { 最小相交距离, 1000000000, -1 };
	
	vec3 最近距离顶点 = {};

	//vec3 camPos = _Vec3(mat[2].m30, mat[2].m31, mat[2].m32);
	vec3 camPos{};

	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			auto* 顶点 = f_buf_VNT_ptr(*me->m_顶点);
			uint32 num = me->m_顶点->m_Mem.m_数量;

			const S_MeshTranformProp& 元素属性 = f_buf_网格元素变换属性_at(me->m_网格元素变换属性);
			auto viewInverseMat = f_mat44_to_33(mat[1]);

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1 = 顶点[i].vert;

				f_lineMeshTranform(v1, 顶点[i].normal, 元素属性, mat[0], viewInverseMat, camPos);

				float32 d = f_graph_点到直线距离(s, dir, v1);

				if (d < 拾取点.相交宽度 && d <= 最小相交距离) {
					拾取点.相交宽度 = d;
					拾取点.点索引 = i;
				}
			}

			break;
		}
	}

	return 拾取点;
}

float32 f_surface_射线与曲线相交(S_Mesh* mesh, const Mat44f mat[2], const vec3& s, const vec3& dir, const vec3& 相机位置, const float32& min距离) {
	uint32 num = mesh->f_get顶点数量();
	if (!num) return false;

	bool 使用索引 = true;
	uvec2* p索引 = nullptr;
	if (mesh->m_索引->m_Mem.m_数量) {
		num = mesh->m_索引->m_Mem.m_数量 / 2;
		p索引 = (uvec2*)f_buf_UI32_ptr(*mesh->m_索引);
	}
	else {
		使用索引 = false;
		num /= 2;
	}


	uint32 线程数 = 16;
	float32 最小相交距离 = 1e+6;
	bool 是否相交 = false;
	vec3 相交点;
	
	auto* point = f_buf_CurvePoint3D_ptr(*mesh->m_顶点);
	for (uint32 i = 0; i < num; ++i) {
		vec3 v1, v2, vR, vL;
		if (使用索引) {
			uvec2 index = p索引[i];
			v1 = point[index.x].value;
			vR = point[index.x].R_point;
			v2 = point[index.y].value;
			vL = point[index.y].L_point;
		}
		else {
			v1 = (point[i * 2].value);
			vR = (point[i * 2].R_point);
			v2 = (point[i * 2 + 1].value);
			vL = (point[i * 2 + 1].L_point);
		}

		vec3 p1 = mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0);

		for (uint32 k = 1; k <= 32; ++k) {
			vec3 p2 = mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0.03125f * k);

			
			float32 拾取距离;
			float32 两线段距离 = f_graph_两线段距离(p1, p2, s, dir, 相交点, min距离);
			if (两线段距离 >= 0) {
				float32 距离 = length(相交点 - 相机位置) * min距离;
				拾取距离 = 两线段距离 / (距离);

				if (拾取距离 < 最小相交距离 && 两线段距离 < 距离) {
					最小相交距离 = 拾取距离;
					是否相交 = true;
				}
			}
			else {
				vec3 中点 = (p2 - p1);
				中点 = 中点 * 0.5 + p1;
				float32 距离 = length(中点 - 相机位置) * min距离;

					拾取距离 = f_graph_点到直线距离(s, dir, 中点);
					if (拾取距离 < 距离) {
						
						拾取距离 = 拾取距离 / (距离);
						if (拾取距离 < 最小相交距离) {
							最小相交距离 = 拾取距离;
							是否相交 = true;
						}
					}
				
			}

			p1 = p2;
		}
	}
	
	if (是否相交) {
		最小相交距离 *= f_mesh_get网格元素绘制属性(mesh).m_DepthScale;
	}
	else {
		最小相交距离 = -1;
	}
	return 最小相交距离;
}

uvec2 f_surface_射线与曲线点相交(S_Mesh* mesh, const Mat44f mat[2], const vec3& s, const vec3& dir, const vec3& 相机位置, const float32& min距离) {
	uint32 num = mesh->f_get顶点数量();

	uvec2 index{ 0xffffffff, 0xffffffff };
	if (!num) return index;

	auto* point = f_buf_CurvePoint3D_ptr(*mesh->m_顶点);

	float32 最近端点 = 1e+6;
	
	for (uint32 i = 0; i < num; ++i) {
		float32 距离1 = length(point[i].value - 相机位置) * min距离;
		float32 距离2 = length(point[i].L_point - 相机位置) * min距离;
		float32 距离3 = length(point[i].R_point - 相机位置) * min距离;

		float32 d1 = f_graph_点到直线距离(s, dir, point[i].value) / 距离1;
		float32 d2 = f_graph_点到直线距离(s, dir, point[i].L_point) / 距离2;
		float32 d3 = f_graph_点到直线距离(s, dir, point[i].R_point) / 距离3;


		if (d1 < 最近端点 && d1 < 距离1) {
			最近端点 = d1;

			index.x = i;
			index.y = 0;
		}

		if (d2 < 最近端点 && d2 < 距离2) {
			最近端点 = d2;

			index.x = i;
			index.y = 1;
		}

		if (d3 < 最近端点 && d3 < 距离1) {
			最近端点 = d3;

			index.x = i;
			index.y = 2;
		}
	}

	return index;
}

float32 f_surface_屏幕拾取曲线(S_Mesh* mesh, const Mat44f mat[3], const vec2& 屏幕坐标, const S_Rect2Df& rect, float32 拾取距离, vec3& 拾取坐标) {
	uint32 num = mesh->f_get顶点数量();
	if (!num) return false;

	bool 使用索引 = true;
	uvec2* p索引 = nullptr;
	if (mesh->m_索引->m_Mem.m_数量) {
		num = mesh->m_索引->m_Mem.m_数量 / 2;
		p索引 = (uvec2*)f_buf_UI32_ptr(*mesh->m_索引);
	}
	else {
		使用索引 = false;
		num /= 2;
	}


	uint32 线程数 = 16;
	float32 最小相交距离 = 拾取距离;
	float32 交点 = -1;
	uvec2 相交线段 = {};
	bool 是否相交 = false;
	

	auto* point = f_buf_CurvePoint3D_ptr(*mesh->m_顶点);
	for (uint32 i = 0; i < num; ++i) {
		vec3 v1, v2, vR, vL;
		if (使用索引) {
			uvec2 index = p索引[i];
			v1 = point[index.x].value;
			vR = point[index.x].R_point;
			v2 = point[index.y].value;
			vL = point[index.y].L_point;
		}
		else {
			v1 = (point[i * 2].value);
			vR = (point[i * 2].R_point);
			v2 = (point[i * 2 + 1].value);
			vL = (point[i * 2 + 1].L_point);
		}


		vec2 p1 = f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0), rect);
		
		for (uint32 k = 1; k <= 32; ++k) {
			vec2 p2 = f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0.03125f * k), rect);

			float32 垂足点 = -1;
			float32 拾取距离 = f_graph_点到线段的距离(屏幕坐标, p1, p2, 垂足点);

			if (拾取距离 < 最小相交距离) {
				最小相交距离 = 拾取距离;
				是否相交 = true;

				交点 = 垂足点;
				相交线段 = {i, k};
				
			}
			p1 = p2;
		}
	}

	if (是否相交) {
		最小相交距离 *= f_mesh_get网格元素绘制属性(mesh).m_DepthScale;

		vec3 v1, v2, vR, vL;
		if (使用索引) {
			uvec2 index = p索引[相交线段.x];
			v1 = point[index.x].value;
			vR = point[index.x].R_point;
			v2 = point[index.y].value;
			vL = point[index.y].L_point;
		}
		else {
			v1 = (point[相交线段.x * 2].value);
			vR = (point[相交线段.x * 2].R_point);
			v2 = (point[相交线段.x * 2 + 1].value);
			vL = (point[相交线段.x * 2 + 1].L_point);
		}
		vec3 p1 = mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0.03125f * (相交线段.y-1));
		vec3 p2 = mat[0] * f_glsl_cal_CubicCurve(v1, vR, v2, vL, 0.03125f * 相交线段.y);
		拾取坐标 = (p2 - p1) * 交点 + p1;
	}
	else {
		最小相交距离 = -1;
	}
	return 最小相交距离;
}

uvec2 f_surface_屏幕拾取曲线控制点(S_Mesh* mesh, const Mat44f mat[3], const vec2& 屏幕坐标, const S_Rect2Df& rect, const float32 min距离) {
	uint32 num = mesh->f_get顶点数量();

	uvec2 index{ 0xffffffff, 0xffffffff };
	if (!num) return index;

	auto* point = f_buf_CurvePoint3D_ptr(*mesh->m_顶点);
	float32 最近端点 = 1e+6;
	//float32 最近控制点 = 1e+6;
	for (uint32 i = 0; i < num; ++i) {
		
		float32 d1 = length(f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * point[i].value, rect) - 屏幕坐标);
		float32 d2 = length(f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * point[i].L_point, rect) - 屏幕坐标);
		float32 d3 = length(f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * point[i].R_point, rect) - 屏幕坐标);


		if (d1 < 最近端点 && d1 < min距离) {
			最近端点 = d1;

			index.x = i;
			index.y = 0;
		}

		if (d2 < 最近端点 && d2 < min距离) {
			最近端点 = d2;

			index.x = i;
			index.y = 1;
		}

		if (d3 < 最近端点 && d3 < min距离) {
			最近端点 = d3;

			index.x = i;
			index.y = 2;
		}
	}

	return index;
}

S_点拾取 f_surface_屏幕拾取点(S_Mesh* mesh, const Mat44f mat[3], const vec2& 屏幕坐标, const S_Rect2Df& rect, float32 min距离) {
	uint32 num = mesh->m_顶点->m_Mem.m_数量;
	if(!num) return {};

	S_点拾取 拾取信息{DEF_PickUp_LineMaxDis, 0, -1};
	auto* point = f_bm_ptr<S_VNTC>(*mesh->m_顶点);

	for (uint32 i = 0; i < num; ++i) {
		float32 d1 = length(f_Project空间坐标转屏幕(mat[1], mat[2], mat[0] * point[i].vert, rect) - 屏幕坐标) - min距离;

		if (d1 < 拾取信息.相交宽度) {
			拾取信息.点索引 = i;
			拾取信息.相交宽度 = d1;
		}
	}

	return 拾取信息;
}


static Inline void f_线段拾取距离(vec3 v[3],
	const Mat44f mat[3], 
	const mat3X3& viewInverseMat, 
	const S_MeshTranformProp& 变换属性, 
	const vec2& 屏幕坐标, 
	const S_Rect2Df& rect, 
	const vec3& camPos,
	const uint32& 线ID,
	S_线拾取& 拾取线, 
	float32& 交点,
	uint32 元素 = 0
	) {

	f_lineMeshTranform(v[0], {}, 变换属性, mat[0], viewInverseMat, camPos);
	f_lineMeshTranform(v[1], {}, 变换属性, mat[0], viewInverseMat, camPos);

	vec2 p1 = f_Project空间坐标转屏幕(mat[1], mat[2], v[0], rect);
	vec2 p2 = f_Project空间坐标转屏幕(mat[1], mat[2], v[1], rect);

	float32 垂足点 = -1;
	float32 点到线段距离 = f_graph_点到线段的距离(屏幕坐标, p1, p2, 垂足点);
	if (点到线段距离 < 拾取线.相交宽度) {
		拾取线.相交宽度 = 点到线段距离;
		拾取线.线索引 = 线ID;
		拾取线.线元素 = 元素;
		交点 = 垂足点;
	}
}

static Inline void f_取三角形边线段顶点(S_Mesh* me, uvec3* 索引, S_线拾取& 拾取线, vec3 point[3]) {
	uvec3 index{};

	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* v = f_buf_VNT_ptr(*me->m_顶点);

			if (索引) {
				index = 索引[拾取线.线索引];
			}
			else {
				index.x = 拾取线.线索引 * 3;
				index.y = index.x + 1;
				index.z = index.y + 1;
			}
			point[0] = v[index.x].vert;
			point[1] = v[index.y].vert;
			point[2] = v[index.z].vert;
			break;
		}
		case E_顶点组合标志::e_坐标_法线: {
			S_VN* v = f_buf_VN_ptr(*me->m_顶点);

			if (索引) {
				index = 索引[拾取线.线索引];
			}
			else {
				index.x = 拾取线.线索引 * 3;
				index.y = index.x + 1;
				index.z = index.y + 1;
			}
			point[0] = v[index.x].vert;
			point[1] = v[index.y].vert;
			break;
		}

		case E_顶点组合标志::e_坐标_颜色: {
			S_VC* v = f_buf_VC_ptr(*me->m_顶点);

			if (索引) {
				index = 索引[拾取线.线索引];
			}
			else {
				index.x = 拾取线.线索引 * 3;
				index.y = index.x + 1;
				index.z = index.y + 1;
			}
			point[0] = v[index.x].vert;
			point[1] = v[index.y].vert;
			point[2] = v[index.z].vert;
			break;
		}
		default: {
			vec3* v = f_buf_Vec3_ptr(*me->m_顶点);

			if (索引) {
				index = 索引[拾取线.线索引];
			}
			else {
				index.x = 拾取线.线索引 * 3;
				index.y = index.x + 1;
				index.z = index.y + 1;
			}
			point[0] = v[index.x];
			point[1] = v[index.y];
			point[2] = v[index.z];
			break;
		}
	}
}

S_线拾取 f_surface_屏幕拾取线段(S_Mesh* mesh, const Mat44f mat[4], const vec2& 屏幕坐标, const S_Rect2Df& rect, const uvec2& Offset_num, float32 最小相交距离, uint32 元素) {
	S_线拾取 拾取线 = { {}, 最小相交距离, 1000000000, -1 };
	
	uint32 num;
	if (Offset_num.y) {
		num = Offset_num.y / 2;
	}
	else {
		num = mesh->m_顶点->m_Mem.m_数量 / 2;
	}
	
	if (!num) return 拾取线;



	vec3 最近距离顶点 = {};
	float32 交点 = -1;


	S_MeshTranformProp 变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 元素);
	auto viewInverseMat = f_mat44_to_33(mat[3]);
	vec3 camPos = mat[3] * vec3{};

	auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;


	for (uint32 i = 0; i < num; ++i) {
		uint32 index = i * 2 + Offset_num.x;

		vec3 point[2] = {};

		switch (*mesh->m_顶点配置Flags) {
			case E_顶点组合标志::e_坐标_法线_UV: {
				//f_buf_VNT_ptr(*mesh->m_顶点);
				S_VNT1* v = (S_VNT1*)顶点指针;

				point[0] = v[index].vert;
				point[1] = v[index + 1].vert;
				break;
			}
			case E_顶点组合标志::e_坐标_法线: {
				//S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
				S_VN* v = (S_VN*)顶点指针;

				point[0] = v[index].vert;
				point[1] = v[index + 1].vert;
				break;
			}

			case E_顶点组合标志::e_坐标_颜色: {
				//S_VC* vc = f_buf_VC_ptr(*mesh->m_顶点);
				S_VC* v = (S_VC*)(顶点指针);

				point[0] = v[index].vert;
				point[1] = v[index + 1].vert;
				
				break;
			}
			default: {
				//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
				vec3* v = (vec3*)(顶点指针);
				point[0] = v[index];
				point[1] = v[index + 1];
				break;
			}
		}

		f_线段拾取距离(point, mat, viewInverseMat, 变换属性, 屏幕坐标, rect, camPos, i, 拾取线, 交点);
	}

	

	if (交点 >= 0) {
		vec3 v1, v2 = { };
		switch (*mesh->m_顶点配置Flags) {
			case E_顶点组合标志::e_坐标_法线_UV: {
				//auto* v = f_buf_VNT_ptr(*mesh->m_顶点);
				auto* v = (S_VNT1*)顶点指针;
				uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
				v1 = v[index].vert;
				v2 = v[index + 1].vert;
				break;
			}
			case E_顶点组合标志::e_坐标_法线: {
				//S_VN* vn= f_buf_VN_ptr(*mesh->m_顶点);
				auto* v = (S_VN*)顶点指针;
				uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
				v1 = v[index].vert;
				v2 = v[index + 1].vert;
				break;
			}
			case E_顶点组合标志::e_坐标_颜色: {
				//S_VC* v = f_buf_VC_ptr(*mesh->m_顶点);
				auto* v = (S_VC*)顶点指针;
				uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
				v1 = v[index].vert;
				v2 = v[index + 1].vert;
				break;
			}
			default: {
				//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
				auto* v = (vec3*)顶点指针;
				uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
				v1 = v[index];
				v2 = v[index + 1];
				break;
			}
		}
		vec3 p1 = mat[0] * v1;
		vec3 p2 = mat[0] * v1;

		拾取线.交点 = (p2 - p1) * 交点 + p1;
	}

	return 拾取线;
}

S_线拾取 f_surface_屏幕拾取线段(S_Mesh* mesh, const Mat44f mat[4], const vec2& 拾取坐标, const S_Rect2Df& rect, float32 拾取距离, uint32 元素) {
	S_线拾取 拾取线 = { {}, 拾取距离, 1000000000, -1 };

	uvec2* 索引;
	uint32 num = mesh->m_索引->m_Mem.m_数量;

	if (num) {
		num /= 2;
		索引 = (uvec2*)f_buf_UI32_ptr(*mesh->m_索引);
	}
	else {
		num = mesh->m_顶点->m_Mem.m_数量 / 2;
		索引 = nullptr;
	}

	if (!num) return 拾取线;


	vec3 最近距离顶点 = {};
	float32 交点 = -1;

	S_MeshTranformProp 变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 元素);
	auto viewInverseMat = f_mat44_to_33(mat[3]);
	vec3 camPos = mat[3] * vec3{};
	//vec3 camPos = (inverse(mat_ProjecView[3]) * vec4(0, 0, 0, 1)).xyz;

	//auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;


	switch (*mesh->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* v = f_buf_VNT_ptr(*mesh->m_顶点);
			//S_VNT1* v = (S_VNT1*)顶点指针;
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 2;
					index.y = index.x + 1;
				}

				vec3 point[2] = {};
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;

				f_线段拾取距离(point, mat, viewInverseMat, 变换属性, 拾取坐标, rect, camPos, i, 拾取线, 交点);
			}
			
			break;
		}
		case E_顶点组合标志::e_坐标_法线: {
			S_VN* v = f_buf_VN_ptr(*mesh->m_顶点);
			//S_VN* v = (S_VN*)顶点指针;
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 2;
					index.y = index.x + 1;
				}

				vec3 point[2] = {};
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;

				f_线段拾取距离(point, mat, viewInverseMat, 变换属性, 拾取坐标, rect, camPos, i, 拾取线, 交点);
			}
			break;
		}

		case E_顶点组合标志::e_坐标_颜色: {
			S_VC* v = f_buf_VC_ptr(*mesh->m_顶点);
			//S_VC* v = (S_VC*)(顶点指针);
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 2;
					index.y = index.x + 1;
				}

				vec3 point[2] = {};
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;

				f_线段拾取距离(point, mat, viewInverseMat, 变换属性, 拾取坐标, rect, camPos, i, 拾取线, 交点);
			}

			break;
		}
		default: {
			vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
			//vec3* v = (vec3*)(顶点指针);
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 2;
					index.y = index.x + 1;
				}

				vec3 point[2] = {};
				point[0] = v[index.x];
				point[1] = v[index.y];

				f_线段拾取距离(point, mat, viewInverseMat, 变换属性, 拾取坐标, rect, camPos, i, 拾取线, 交点);
			}
			break;
		}
	}
	
	if (交点 >= 0) {
		uvec2 index{};
		vec3 point[2] = {};
		switch (*mesh->m_顶点配置Flags) {
			case E_顶点组合标志::e_坐标_法线_UV: {
				S_VNT1* v = f_buf_VNT_ptr(*mesh->m_顶点);
				
				if (索引) {
					index = 索引[拾取线.线索引];
				}
				else {
					index.x = 拾取线.线索引 * 2;
					index.y = index.x + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				break;
			}
			case E_顶点组合标志::e_坐标_法线: {
				S_VN* v = f_buf_VN_ptr(*mesh->m_顶点);
				
				uvec2 index;
				if (索引) {
					index = 索引[拾取线.线索引];
				}
				else {
					index.x = 拾取线.线索引 * 2;
					index.y = index.x + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				break;
			}

			case E_顶点组合标志::e_坐标_颜色: {
				S_VC* v = f_buf_VC_ptr(*mesh->m_顶点);
				uvec2 index;
				if (索引) {
					index = 索引[拾取线.线索引];
				}
				else {
					index.x = 拾取线.线索引 * 2;
					index.y = index.x + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				break;
			}
			default: {
				vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
				uvec2 index;
				if (索引) {
					index = 索引[拾取线.线索引];
				}
				else {
					index.x = 拾取线.线索引 * 2;
					index.y = index.x + 1;
				}
				point[0] = v[index.x];
				point[1] = v[index.y];
				break;
			} 
		}
		vec3 p1 = mat[0] * point[0];
		vec3 p2 = mat[0] * point[1];

		拾取线.交点 = (p2 - p1) * 交点 + p1;
	}
	else {
		拾取线.相交宽度 = -1;
	}
	return 拾取线;
}

S_线拾取 f_surface_屏幕拾取线段(S_Mesh* mesh, const Mat44f mat[3], const vec2& 拾取坐标, const S_Rect2Df& rect, float32 拾取距离) {
	S_线拾取 拾取线 = { {}, 拾取距离, DEF_PickUp_LineMaxDis, -1 };

	uvec2* 索引 = (uvec2*)f_bm_ptr<uint32>(*mesh->m_索引);
	uint32 num = mesh->m_索引->m_Mem.m_数量 / 2;

	if (!num) return 拾取线;
	auto* v = f_bm_ptr<S_VNTC>(*mesh->m_顶点);

	mat3 invRot;
	switch (mesh->m_顶点变换模式) {
		case DEF_3DTranform_LookAt: {
			invRot = f_mat44_to_33(f_mat44_Invert(mat[2]));
			break;
		}
		default: {
		}
	}


	for (uint32 i = 0; i < num; ++i) {
		uvec2 index = 索引[i];
		
		vec3 point[2];
		switch (mesh->m_顶点变换模式) {
			case DEF_3DTranform_LookAt: {
				point[0] = invRot * v[index.x].vert;
				point[1] = invRot * v[index.y].vert;

				point[0] = mat[0] * point[0];
				point[1] = mat[0] * point[1];
				break;
			}
			default: {
				point[0] = mat[0] * v[index.x].vert;
				point[1] = mat[0] * v[index.y].vert;
			}
		}
		

		vec2 p1 = f_Project空间坐标转屏幕(mat[1], mat[2], point[0], rect);
		vec2 p2 = f_Project空间坐标转屏幕(mat[1], mat[2], point[1], rect);

		float32 垂足点 = -1;
		float32 点到线段距离 = f_graph_点到线段的距离(拾取坐标, p1, p2, 垂足点);
		if (点到线段距离 < 拾取线.相交宽度) {
			拾取线.相交宽度 = 点到线段距离;
			拾取线.线索引 = i;
			拾取线.交点.z = 垂足点;
		}
	}

	return 拾取线;
}


S_线拾取 f_surface_正面拾取屏幕线段(S_Mesh* mesh, const Mat44f mat[3], const vec2& 拾取坐标, const S_Rect2Df& rect, float32 拾取距离) {
	S_线拾取 拾取线 = { {}, 拾取距离, DEF_PickUp_LineMaxDis, -1 };

	uvec2* 索引 = (uvec2*)f_bm_ptr<uint32>(*mesh->m_索引);
	uint32 num = mesh->m_索引->m_Mem.m_数量 / 2;

	if (!num) return 拾取线;
	auto* v = f_bm_ptr<S_VNTC>(*mesh->m_顶点);

	for (uint32 i = 0; i < num; ++i) {
		uvec2 index = 索引[i];

		vec3 point[2];
		point[0] = mat[0] * v[index.x].vert;
		point[1] = mat[0] * v[index.y].vert;

		vec2 p1 = f_Project空间坐标转屏幕(mat[1], mat[2], point[0], rect);
		vec2 p2 = f_Project空间坐标转屏幕(mat[1], mat[2], point[1], rect);

		float32 垂足点 = -1;
		float32 点到线段距离 = f_graph_点到线段的距离(拾取坐标, p1, p2, 垂足点);
		if (点到线段距离 < 拾取线.相交宽度) {
			
			vec3 n1 = f_mat44_to_33(mat[1] * mat[2] * mat[0]) * v[index.x].normal;
			vec3 n2 = f_mat44_to_33(mat[1] * mat[2] * mat[0]) * v[index.y].normal;
			vec3 n = normalize(n1 + n2);

			if (n.z <= 0) {
				拾取线.相交宽度 = 点到线段距离;
				拾取线.线索引 = i;
				拾取线.交点.z = 垂足点;
			}

		}
	}

	return 拾取线;
}






S_线拾取 f_surface_屏幕拾取三角形边(S_Mesh* mesh, const Mat44f mat[4], const vec2& 屏幕坐标, const S_Rect2Df& rect, float32 拾取距离, uint32 元素, bool 计数交点) {
	S_线拾取 拾取线 = { {}, 拾取距离, 1000000000, -1 };

	uvec3* 索引;
	uint32 num = mesh->m_索引->m_Mem.m_数量;

	if (num) {
		num /= 3;
		索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);
	}
	else {
		num = mesh->m_顶点->m_Mem.m_数量 / 3;
		索引 = nullptr;
	}

	if (!num) return 拾取线;


	vec3 最近距离顶点 = {};
	float32 交点 = -1;

	S_MeshTranformProp 变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 元素);
	auto viewInverseMat = f_mat44_to_33(mat[3]);
	vec3 camPos = mat[3] * vec3{};

	//auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;

	for (uint32 i = 0; i < num; ++i) {
		uvec3 index;
		vec3 point[3];
		switch (*mesh->m_顶点配置Flags) {
			case E_顶点组合标志::e_坐标_法线_UV: {
				S_VNT1* v = f_buf_VNT_ptr(*mesh->m_顶点);
				
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 3;
					index.y = index.x + 1;
					index.z = index.y + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				point[2] = v[index.z].vert;
				break;
			}
			case E_顶点组合标志::e_坐标_法线: {
				S_VN* v = f_buf_VN_ptr(*mesh->m_顶点);
				
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 3;
					index.y = index.x + 1;
					index.z = index.y + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				point[2] = v[index.z].vert;
				break;
			}

			case E_顶点组合标志::e_坐标_颜色: {
				S_VC* v = f_buf_VC_ptr(*mesh->m_顶点);
				
				uvec3 index;
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 3;
					index.y = index.x + 1;
					index.z = index.y + 1;
				}
				point[0] = v[index.x].vert;
				point[1] = v[index.y].vert;
				point[2] = v[index.z].vert;
				break;
			}
			default: {
				vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
				
				if (索引) {
					index = 索引[i];
				}
				else {
					index.x = i * 3;
					index.y = index.x + 1;
					index.z = index.y + 1;
				}
				point[0] = v[index.x];
				point[1] = v[index.y];
				point[2] = v[index.z];
				break;
			}
		}

		vec3 edge[2];
		edge[0] = point[0];
		edge[1] = point[1];
		f_线段拾取距离(edge, mat, viewInverseMat, 变换属性, 屏幕坐标, rect, camPos, i, 拾取线, 交点, 0);

		edge[0] = point[1];
		edge[1] = point[2];
		f_线段拾取距离(edge, mat, viewInverseMat, 变换属性, 屏幕坐标, rect, camPos, i, 拾取线, 交点, 1);

		edge[0] = point[2];
		edge[1] = point[0];
		f_线段拾取距离(edge, mat, viewInverseMat, 变换属性, 屏幕坐标, rect, camPos, i, 拾取线, 交点, 2);
	}


	if (计数交点 && 交点 >= 0) {
		vec3 point[3] = {};
		f_取三角形边线段顶点(mesh, 索引, 拾取线, point);
		
		vec3 p1;
		vec3 p2;
		switch (拾取线.线元素) {
			case 0: p1 = mat[0] * point[0]; p2 = mat[0] * point[1]; break;
			case 1: p1 = mat[0] * point[1]; p2 = mat[0] * point[2]; break;
			case 2: p1 = mat[0] * point[2]; p2 = mat[0] * point[0]; break;
			default:
				break;
		}
		
		拾取线.交点 = (p2 - p1) * 交点 + p1;
	}
	else {
		拾取线.相交宽度 = -1;
	}
	return 拾取线;
}


bool f_surface_框选线段(S_Mesh* mesh, const Mat44f& mat, const vec4 平面[5]) {
	uint32 num = mesh->m_顶点->m_Mem.m_数量 / 2;
	if (!num) return false;

	vec3 最近距离顶点 = {};
	int32 最近相交ID = -1;
	float32 最近相交距离 = 100000000;
	
	switch (*mesh->m_顶点配置Flags) {
	
		case E_顶点组合标志::e_坐标_法线: {
			S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
		
			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;
				uint32 index = i * 2;
				v1 = mat * vn[index].vert;
				v2 = mat * vn[index + 1].vert;
	
				vec3 相交点{};
				float32 两线段距离 = 0;
				if (两线段距离 < 最近相交距离) {
					最近相交距离 = 两线段距离;
					最近相交ID = i;
					最近距离顶点 = 相交点;
				}
			}
			//距离 = vec_len(最近距离顶点 - s);
		}
		case E_顶点组合标志::e_坐标_颜色: {
			S_VC* vc = f_buf_VC_ptr(*mesh->m_顶点);
		
			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;
				uint32 index = i * 2;
				v1 = mat * vc[index].vert;
				v2 = mat * vc[index + 1].vert;


				bool 有相交 = true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;


				vec3 相交点;
				for (uint32 j = 0; j < 5; ++j) {
					有相交 = true;
					if (f_graph_线段平面相交(v1, v2, 平面[j], 相交点)) {
						for (uint32 k = 0; k < 5; ++k) {
							if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
								有相交 = false;
								break;
							}
						}
						if (有相交) return true;
					}
				}
			}
		}
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* vc = f_buf_VNT_ptr(*mesh->m_顶点);
	
			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;
				uint32 index = i * 2;
				v1 = mat * vc[index].vert;
				v2 = mat * vc[index + 1].vert;
			

				bool 有相交 = true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;



				vec3 相交点;
				for (uint32 j = 0; j < 5; ++j) {
					有相交 = true;
					if (f_graph_线段平面相交(v1, v2, 平面[j], 相交点)) {
						for (uint32 k = 0; k < 5; ++k) {
							if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
								有相交 = false;
								break;
							}
						}
						if (有相交) return true;
					}
				}
			}
		}
		default : {
			vec3* v = (vec3*)f_buf_Vec3_ptr(*mesh->m_顶点);
	
			for (uint32 i = 0; i < num; ++i) {
				uvec2 index;
				index.x = i * 2;
				index.y = i * 2 + 1;
				vec3 v1 = mat * v[index.x];
				vec3 v2 = mat * v[index.y];
	
	
				vec3 相交点{};
				float32 两线段距离=0;
				if (两线段距离 < 最近相交距离) {
					最近相交距离 = 两线段距离;
					最近相交ID = i;
					最近距离顶点 = 相交点;
				}
			}
			break;
		}
	}

	return false;
}


bool f_surface_框选面线框(S_Mesh* mesh, const Mat44f& mat, const vec4 平面[5]) {
	uint32 num = mesh->m_索引->m_Mem.m_数量 / 3;
	if (!num) return false;

	vec3 最近距离顶点 = {};
	int32 最近相交ID = -1;
	float32 最近相交距离 = 100000000;
	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);

	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		S_VNT1* vc = f_buf_VNT_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;
			uvec3 index = p索引[i];
			v1 = mat * vc[index.x].vert;
			v2 = mat * vc[index.y].vert;
			v3 = mat * vc[index.z].vert;


			bool 有相交 = true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if(有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v3, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;


			
			vec3 相交点;
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = true;
				if (f_graph_线段平面相交(v1, v2, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}
			
			
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = false;
				if (f_graph_线段平面相交(v2, v3, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}


			for (uint32 j = 0; j < 5; ++j) {
				有相交 = false;
				if (f_graph_线段平面相交(v3, v1, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}
			

			if (最近相交ID >= 0) {
				cout << "线框3 " << 最近相交ID << std::endl;
			}
		}
	}
	else {
		vec3* v = (vec3*)f_buf_Vec3_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			uvec2 index;
			index.x = i * 2;
			index.y = i * 2 + 1;
			vec3 v1 = mat * v[index.x];
			vec3 v2 = mat * v[index.y];


			vec3 相交点{};
			float32 两线段距离 = 0;
			if (两线段距离 < 最近相交距离) {
				最近相交距离 = 两线段距离;
				最近相交ID = i;
				最近距离顶点 = 相交点;
			}
		}
	}

	return false;
}

bool f_surface_框选面(S_Mesh* mesh, const mat4& mat, const vec4 平面[5], const vec3 视锥[4][2]) {
	S_VNTC* vert = f_bm_ptr<S_VNTC>(*mesh->m_顶点);
	uvec3* index = (uvec3*)f_bm_ptr<uint32>(*mesh->m_索引);

	uint32 num = mesh->m_索引->m_Mem.m_数量 / 3;


	mat3 invRot;
	switch (mesh->m_顶点变换模式) {
		case DEF_3DTranform_LookAt: {
			invRot = f_mat4_to_mat3(f_mat4_Invert(mat));
			break;
		}
		default: {
		}
	}

	const uint8 面ID组[4][2] = {
		{2,3},
		{2,3},
		{0,1},
		{0,1},
	};

	
	for (uint32 i = 0; i < num; ++i) {
		uvec3 trangle = index[i];

		vec3 v1 = vert[trangle.x].vert;
		vec3 v2 = vert[trangle.y].vert;
		vec3 v3 = vert[trangle.z].vert;

		switch (mesh->m_顶点变换模式) {
			case DEF_3DTranform_LookAt: {

				v1 = invRot * v1;
				v2 = invRot * v2;
				v3 = invRot * v3;

				v1 = mat * v1;
				v2 = mat * v2;
				v3 = mat * v3;
				break;
			}
			default: {
				v1 = mat * v1;
				v2 = mat * v2;
				v3 = mat * v3;
			}
		}

		uint8 有相交[3] = {};
		for (uint32 k = 0; k < 5; ++k) {
			float32 d1 = f_graph_点到平面距离(v1, 平面[k]);
			float32 d2 = f_graph_点到平面距离(v2, 平面[k]);
			float32 d3 = f_graph_点到平面距离(v3, 平面[k]);

			有相交[0] += d1 > 0 ? 1 : 0;
			有相交[1] += d2 > 0 ? 1 : 0;
			有相交[2] += d3 > 0 ? 1 : 0;
		}

		if (有相交[0] >= 5 || 有相交[1] >= 5 || 有相交[1] >= 5) {
			return true;
		}
		

		vec3 交点{};
		for (uint32 当前视锥面ID = 0; 当前视锥面ID < 4; ++当前视锥面ID) {
			if (f_graph_线段平面相交(v1, v2, 平面[当前视锥面ID], 交点)) {
				float32 d1 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][0] ] );
				float32 d2 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][1] ] );
				if(d1 > 0 && d2 > 0) 
					return true;
			}

			if (f_graph_线段平面相交(v2, v3, 平面[当前视锥面ID], 交点)) {
				float32 d1 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][0] ] );
				float32 d2 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][1] ] );
				if(d1 > 0 && d2 > 0) 
					return true;
			}

			if (f_graph_线段平面相交(v3, v1, 平面[当前视锥面ID], 交点)) {
				float32 d1 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][0] ] );
				float32 d2 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][1] ] );
				if(d1 > 0 && d2 > 0) 
					return true;
			}
		}

		for (uint32 i = 0; i < 4; ++i) {
			bool isPick = f_intersect_射线三角形(v1, v2, v3, (视锥[i][0]), (视锥[i][1]));
			//vec3 uvt;
			//bool isPick = f_intersect_射线三角形(v1, v2, v3, (视锥[i][0]), (视锥[i][1]), &uvt);
			if (isPick) {
				return true;
			}
		}
	}

	return false;
}

bool f_surface_框选网格边框(S_Mesh* mesh, const Mat44f mat[2], const vec4 平面[5]) {
	uint32 num = mesh->m_索引->m_Mem.m_数量 / 2;
	if (!num) return false;

	vec3 最近距离顶点 = {};
	int32 最近相交ID = -1;
	float32 最近相交距离 = 100000000;

	const auto& 元素变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 0);
	vec3 camPos{};

	switch (*mesh->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* vc = f_buf_VNT_ptr(*mesh->m_顶点);
			uvec2* index = (uvec2*)f_buf_UI32_ptr(*mesh->m_索引);

			auto viewInverseMat = f_mat44_to_33(mat[1]);

			for (uint32 i = 0; i < num; ++i) {
				vec3 v1, v2;
				v1 = vc[index[i].x].vert;
				v2 = vc[index[i].y].vert;

				f_lineMeshTranform(v1, vc[index[i].x].normal, 元素变换属性, mat[0], viewInverseMat, camPos);
				f_lineMeshTranform(v2, vc[index[i].y].normal, 元素变换属性, mat[0], viewInverseMat, camPos);
				

				bool 有相交 = true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;
				for (uint32 j = 0; j < 5; ++j) {
					if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
						有相交 = false;
						continue;
					}
				}
				if (有相交) return true;



				vec3 相交点;
				for (uint32 j = 0; j < 5; ++j) {
					有相交 = true;
					if (f_graph_线段平面相交(v1, v2, 平面[j], 相交点)) {
						for (uint32 k = 0; k < 5; ++k) {
							if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
								有相交 = false;
								break;
							}
						}
						if (有相交) return true;
					}
				}

			}
		}
		case E_顶点组合标志::e_坐标_法线: {
		}
		case E_顶点组合标志::e_坐标_颜色: {
		}
		default: {
			break;
		}
	}

	return false;
}

//bool f_surface_框选点包围盒(const S_Cube& cube, const vec3& position, const vec4 平面[5]) {
//	vec3 vert[8];
//
//	vert[0] = cube.pos - cube.size + position;
//	vert[1] = cube.pos + cube.size + position;
//
//	vert[2] = { vert[1].x, vert[0].y, vert[0].z };
//	vert[3] = { vert[0].x, vert[1].y, vert[0].z };
//	vert[4] = { vert[0].x, vert[0].y, vert[1].z };
//
//	vert[5] = { vert[0].x, vert[1].y, vert[1].z };
//	vert[6] = { vert[1].x, vert[0].y, vert[1].z };
//	vert[7] = { vert[1].x, vert[1].y, vert[0].z };
//
//
//	for (uint32 i = 0; i < 8; ++i) {
//		bool 有相交 = true;
//		for (uint32 k = 0; k < 5; ++k) {
//			if (f_graph_点到平面距离(vert[i], 平面[k]) < 0) {
//				有相交 = false;
//				break;
//			}
//		}
//		if(有相交) return true;
//	}
//
//	return false;
//}

static void f_构建包围盒空间顶点(const S_Cube& cube, const vec3& position, vec3 vert[8], uvec2 index[12]) {
	vert[0] = cube.pos - cube.size + position;
	vert[1] = cube.pos + cube.size + position;

	vert[2] = { vert[1].x, vert[0].y, vert[0].z };
	vert[3] = { vert[0].x, vert[1].y, vert[0].z };
	vert[4] = { vert[0].x, vert[0].y, vert[1].z };

	vert[5] = { vert[0].x, vert[1].y, vert[1].z };
	vert[6] = { vert[1].x, vert[0].y, vert[1].z };
	vert[7] = { vert[1].x, vert[1].y, vert[0].z };


	index[0] = {0,2};
	index[1] = {0,3};
	index[2] = {3,7};
	index[3] = {2,7};
	
	index[4] = {4,6};
	index[5] = {4,5};
	index[6] = {5,1};
	index[7] = {6,1};
	
	index[8] = {0,4};
	index[9] = {3,5};
	index[10] = {2,6};
	index[11] = {7,1};
	
}
bool f_surface_框选包围盒(const S_Cube& cube, const vec3& position, const vec4 平面[5], const vec3 视锥[4][2]) {
	vec3 vert[8];
	uvec2 index[12] = {};
	f_构建包围盒空间顶点(cube, position, vert, index);

	uint8 被包含[8] = {};
	for (uint32 i = 0; i < 8; ++i) {
		bool 有相交[5] = {false};

		for (uint32 k = 0; k < 5; ++k) {
			float32 d = f_graph_点到平面距离(vert[i], 平面[k]);
			if (d > 0) {
				有相交[k] = true;
			}
			else {
				++被包含[i];
			}
		}

		if (有相交[0] && 有相交[1] && 有相交[2] && 有相交[3] && 有相交[4]) {
			return true;
		}
	}

	if (被包含[0] >= 8 || 被包含[1] >= 8 || 被包含[2] >= 8 || 被包含[3] >= 8 || !被包含[4] >= 8) {
		return false;
	}
	for (uint32 i = 0; i < 4; ++i) {
		bool isPick = f_intersect_RayAndAABB((float32*)&(视锥[i][0]), (float32*)&(视锥[i][1]), (float32*)&(vert[0]), (float32*)&(vert[1]));
		if (isPick) {
			return true;
		}
	}
	
	const uint8 面ID组[4][2] = {
		{2,3},
		{2,3},
		{0,1},
		{0,1},
	};

	for (uint32 i = 0; i < 12; ++i) {
		vec3 交点{};

		for (uint32 当前视锥面ID = 0; 当前视锥面ID < 4; ++当前视锥面ID) {
			if (f_graph_线段平面相交(vert[index[i].x], vert[index[i].y], 平面[当前视锥面ID], 交点)) {
				
				float32 d1 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][0] ] );
				float32 d2 = f_graph_点到平面距离(交点, 平面[ 面ID组[当前视锥面ID][1] ] );
				if(d1 > 0 && d2 > 0) 
					return true;
			}
		}
	}



	return false;
}

bool f_surface_框选包围盒(const S_Cube& cube, const Mat44f 相机矩阵[2], const S_Rect2Df& view, const S_Bounding2& bound) {
	vec3 vert[8];
	std::vector<vec2> vert_proj(8);
	uvec2 index[12] = {};
	f_构建包围盒空间顶点(cube, {}, vert, index);


	// 检查点是否在矩形内（包括边界）
	auto pointInRect = [&](vec2 p) {
		return (p.x >= bound.min.x - 1e-6 && p.x <= bound.max.x + 1e-6 &&
				p.y >= bound.min.y - 1e-6 && p.y <= bound.max.y + 1e-6);
	};

	auto 点在多边形内 = [&](vec2 p) {
		bool inside = false;
		uint32 num = vert_proj.size();
		for (int32 i = 0, k = num - 1; i < num; k=i, ++i) {
			//uvec2 index_r = index[i];
			vec2 开始顶点坐标 = vert_proj[k];
			vec2 结束顶点坐标 = vert_proj[i];

			// 检查点是否在边上
			vec2 edge = 开始顶点坐标 - 结束顶点坐标;
			vec2 toPoint = p - 结束顶点坐标;
			float32 crs = cross(edge, toPoint);

			if (fabs(crs) < 1e-8) {
				float32 minX = min(结束顶点坐标.x, 开始顶点坐标.x);
				float32 maxX = max(结束顶点坐标.x, 开始顶点坐标.x);
				float32 minY = min(结束顶点坐标.y, 开始顶点坐标.y);
				float32 maxY = max(结束顶点坐标.y, 开始顶点坐标.y);

				if (p.x >= minX - 1e-8 && p.x <= maxX + 1e-8 &&
					p.y >= minY - 1e-8 && p.y <= maxY + 1e-8) {
					return true;
				}
			}

			// 计算边的长度平方（避免开方）
			//float32 edge_len_sq = edge.x * edge.x + edge.y * edge.y;

			// 针对细长边优化的共线判断：叉积与边长平方的比例
			//if (abs(crs) < 1e-8 * edge_len_sq) {
			//	// 用参数t判断点是否在边上（0 ≤ t ≤ 1）
			//	float32 t;
			//	if (edge_len_sq > 1e-8) {
			//		t = (toPoint.x * edge.x + toPoint.y * edge.y) / edge_len_sq;
			//		if (t >= -1e-8 && t <= 1.0 + 1e-8) {
			//			return true;
			//		}
			//	}
			//}

			// 确保边的两个端点不都在射线的同一侧
			//bool vi_above = 开始顶点坐标.y > p.y + 1e-8;
			//bool vj_above = 结束顶点坐标.y > p.y + 1e-8;
			//
			//if (vi_above == vj_above) {
			//	continue;  // 同侧，不相交
			//}

			// 对于接近水平的边，使用垂直射线判断，避免精度问题
			//bool is_near_horizontal = abs(开始顶点坐标.y - 结束顶点坐标.y) < abs(开始顶点坐标.x - 结束顶点坐标.x) * 1e-8;
			//if (is_near_horizontal) {
			//	// 接近水平的边，改用垂直向上射线判断
			//	if (((开始顶点坐标.x > p.x) != (结束顶点坐标.x > p.x)) &&
			//		(p.y < 结束顶点坐标.y + (开始顶点坐标.y - 结束顶点坐标.y) * (p.x - 结束顶点坐标.x) / (开始顶点坐标.x - 结束顶点坐标.x + 1e-8))) {
			//		inside = !inside;
			//	}
			//} else {
			//	// 普通情况用水平向右射线
			//	if (((开始顶点坐标.y > p.y) != (结束顶点坐标.y > p.y)) &&
			//		(p.x < 结束顶点坐标.x + (开始顶点坐标.x - 结束顶点坐标.x) * (p.y - 结束顶点坐标.y) / (开始顶点坐标.y - 结束顶点坐标.y + 1e-8))) {
			//		inside = !inside;
			//	}
			//}

			if ( ((结束顶点坐标.y > p.y) != (开始顶点坐标.y > p.y)) &&
					(p.x < 结束顶点坐标.x + (开始顶点坐标.x - 结束顶点坐标.x) * (p.y - 结束顶点坐标.y) / (开始顶点坐标.y - 结束顶点坐标.y))
				 ) {
				inside = !inside;
			}
		}
		return inside;
	};

	uint32 顶点在视锥内 = 0;
	for (uint32 i = 0; i < 8; ++i) {
		//vert_proj[i] = f_Project空间坐标转屏幕(相机矩阵[0], 相机矩阵[1], vert[i], view);
		auto v = f_proj_空间坐标转屏幕(相机矩阵[0], 相机矩阵[1], vert[i], view);
		vert_proj[i] = _Vec2(v.x, v.y);
		if (v.z < 1) {
			++顶点在视锥内;
		}
	}
	if(顶点在视锥内 <= 0) return false;

	vert_proj = f_凸包_构建(vert_proj.data(), 8);
	

	for (uint32 i = 0; i < vert_proj.size(); ++i) {
		if (pointInRect(vert_proj[i])) {
			return true;
		}
	}


	vec2 rectPoints[4] = {
		bound.min,
		{bound.max.x, bound.min.y},
		bound.max,
		{bound.min.x, bound.max.y}
	};
	for (uint32 i = 0; i < 4; ++i) {
		if (点在多边形内(rectPoints[i])) {
			return true;
		}
	}


	for (uint32 i = 0, 顶点结束索引 = vert_proj.size() - 1; i < vert_proj.size(); 顶点结束索引 = i, ++i) {
		for (int32 k = 0, 包围盒结束索引 = 3; k < 4; 包围盒结束索引 = k, ++k) {
			if (f_intersect_线段相交(vert_proj[i], vert_proj[顶点结束索引], rectPoints[k], rectPoints[包围盒结束索引])) {
				return true;
			}
		}
	}

	return false;
}

//bool f_surface_框选包围盒(S_Mesh* me, const Mat44f& mat, const vec4 平面[5]) {
//	vec3 vert[8];
//	
//	vert[0] = mat * f_me_getBound(me).min;
//	vert[1] = mat * f_me_getBound(me).max;
//
//	vert[2] = { vert[1].x, vert[0].y, vert[0].z };
//	vert[3] = { vert[0].x, vert[1].y, vert[0].z };
//	vert[4] = { vert[0].x, vert[0].y, vert[1].z };
//
//	vert[5] = { vert[0].x, vert[1].y, vert[1].z };
//	vert[6] = { vert[1].x, vert[0].y, vert[1].z };
//	vert[7] = { vert[1].x, vert[1].y, vert[0].z };
//
//
//	for (uint32 i = 0; i < 8; ++i) {
//		bool 有相交 = true;
//		for (uint32 k = 0; k < 5; ++k) {
//			if (f_graph_点到平面距离(vert[i], 平面[k]) > 0) {
//				有相交 = false;
//				break;
//			}
//		}
//		if(有相交) return true;
//	}
//
//	return false;
//}

void f_surface_网格内点(S_Mesh* me, const Mat44f& mat, const S_Vec3Array* vert, S_BoolArray* 是内部, bool 反向) {
	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* VNT = f_buf_VNT_ptr(*me->m_顶点);
			uvec3* index = (uvec3*)f_buf_UI32_ptr(*me->m_索引);

			uint32 num = me->m_索引->m_Mem.m_数量 / 3;
			for (uint32 i = 0; i < num; ++i) {
				VNT[index[i].x].vert;
				VNT[index[i].y].vert;
				VNT[index[i].z].vert;
			}

			break;
		}
	}
}


bool f_surface_屏幕拾取网格(S_Mesh* mesh, const mat4& 网格变换, const Mat44f mat[2], const S_Rect2Df& view, const S_Bounding2& 框) {
	S_VNTC* vert = f_bm_ptr<S_VNTC>(*mesh->m_顶点);
	uvec3* index = (uvec3*)f_bm_ptr<uint32>(*mesh->m_索引);

	uint32 num = mesh->m_索引->m_Mem.m_数量 / 3;


	mat3 invRot;
	switch (mesh->m_顶点变换模式) {
		case DEF_3DTranform_LookAt: {
			invRot = f_mat44_to_33(f_mat44_Invert(mat[1]));
			break;
		}
		default: {
		}
	}

	vec2 rectPoints[4] = {
		框.min,
		{框.max.x, 框.min.y},
		框.max,
		{框.min.x, 框.max.y}
	};

	S_Rect2Df rect;
	rect.offset = 框.min;
	rect.extent = 框.max - 框.min;

	for (uint32 i = 0; i < num; ++i) {
		uvec3 trangle = index[i];

		vec3 v1 = mat[0] * vert[trangle.x].vert;
		vec3 v2 = mat[0] * vert[trangle.y].vert;
		vec3 v3 = mat[0] * vert[trangle.z].vert;

		switch (mesh->m_顶点变换模式) {
			case DEF_3DTranform_LookAt: {
				
				v1 = invRot * vert[trangle.x].vert;
				v2 = invRot * vert[trangle.y].vert;
				v3 = invRot * vert[trangle.z].vert;

				v1 = 网格变换 * v1;
				v2 = 网格变换 * v2;
				v3 = 网格变换 * v3;
				break;
			}
			default: {
				v1 = 网格变换 * vert[trangle.x].vert;
				v2 = 网格变换 * vert[trangle.y].vert;
				v3 = 网格变换 * vert[trangle.z].vert;
			}
		}

		//vec2 三角形[3];
		//三角形[0] = f_Project空间坐标转屏幕(mat[0], mat[1], v1, view);
		//三角形[1] = f_Project空间坐标转屏幕(mat[0], mat[1], v2, view);
		//三角形[2] = f_Project空间坐标转屏幕(mat[0], mat[1], v3, view);

		vec3 投影顶点[3];
		投影顶点[0] = f_proj_空间坐标转屏幕(mat[0], mat[1], v1, view);
		投影顶点[1] = f_proj_空间坐标转屏幕(mat[0], mat[1], v2, view);
		投影顶点[2] = f_proj_空间坐标转屏幕(mat[0], mat[1], v3, view);

		uint8 包含[3] = {0, 0, 0};
		if (投影顶点[0].z < 1 || 投影顶点[1].z < 1 || 投影顶点[2].z < 1) {
			

			//if (投影顶点[0].x < 框.min.x || 投影顶点[0].y < 框.min.y) {
			//	++包含[0];
			//}
			//else {
			//	//包含 = true;
			//}
			//if (投影顶点[0].x > 框.max.x || 投影顶点[0].y > 框.max.y) {
			//	++包含[0];
			//}
			//else {
			//	//包含 = true;
			//}
			//
			//if (投影顶点[1].x < 框.min.x || 投影顶点[1].y < 框.min.y) {
			//	++包含[1];
			//}
			//else {
			//	//包含 = true;
			//}
			//if (投影顶点[1].x > 框.max.x || 投影顶点[1].y > 框.max.y) {
			//	++包含[1];
			//}
			//else {
			//	//包含 = true;
			//}
			//
			//if (投影顶点[2].x < 框.min.x || 投影顶点[2].y < 框.min.y) {
			//	++包含[2];
			//}
			//else {
			//	//包含 = true;
			//}
			//if (投影顶点[2].x > 框.max.x || 投影顶点[2].y > 框.max.y) {
			//	++包含[2];
			//}
			//else {
			//	//包含 = true;
			//}
			//
			//uint8 mask = (包含[0] + 包含[1] + 包含[2]);
			//if ( mask <= 0 || mask >= 3 ) {
			//	//return true;
			//}
			//continue;
			
			vec2 三角形[3] = {_Vec2(投影顶点[0]), _Vec2(投影顶点[1]), _Vec2(投影顶点[2])};

			if (f_intersect_点在矩形内(框, 三角形[0]) || f_intersect_点在矩形内(框, 三角形[1]) || f_intersect_点在矩形内(框, 三角形[2])) {
				return true;
			}

			for (uint32 b_id = 0; b_id < 4; ++b_id) {
				if (f_intersect_点在三角形内(rectPoints[b_id], 三角形)) {
					return true;
				}
			}

			for (uint32 i = 0, 顶点结束索引 = 3 - 1; i < 3; 顶点结束索引 = i, ++i) {
				for (int32 k = 0, 包围盒结束索引 = 3; k < 4; 包围盒结束索引 = k, ++k) {
					if (f_intersect_线段相交(三角形[i], 三角形[顶点结束索引], rectPoints[k], rectPoints[包围盒结束索引])) {
						return true;
					}
				}
			}
		}
	}


	return false;
}



void f_surface_fill顶点骨骼(S_Mesh* me, std::vector<S_VertBone>& 顶点骨骼) {
	f_gbuf_fill(*me->m_顶点骨骼属性, 顶点骨骼.data(), 0, 顶点骨骼.size());
}

void f_surface_fill骨骼映射(S_Mesh* me, std::vector<S_BoneMap>& 骨骼映射) {
	f_gbuf_fill(*me->m_骨骼权重映射, 骨骼映射.data(), 0, 骨骼映射.size());
}

void f_surface_设置网格平滑模式(const S_Mesh* me, S_BoolArray* 平直) {
	auto* face = f_buf_面元素_ptr(*me->m_面);

	uint32 num = me->m_面->m_Mem.m_数量;
	bool 平直多例 = 平直->count >= num;

	for (uint32 i = 0; i < num; ++i) {
		face[i].FacesMooth = 平直多例 ? 平直->ptr_userData[i] : 平直->ptr_userData[0];
	}
}

void f_surface_材质面区间(S_Mesh* me, S_材质管线* 默认材质) {
	uint32 num = me->m_面->m_Mem.m_数量;
	if(num < 2) return;
	--num;

	auto* face = f_buf_面元素_ptr(*me->m_面);

	std::vector<uint32> 开始索引;
	for (uint32 i = 0; i < num; ++i) {
		if (face[i].MaterialSlot != face[i + 1].MaterialSlot) {
			开始索引.push_back(i+1);
		}
	}
	num = 开始索引.size();

	auto* s = 开始索引.data();
	std::vector<uvec2> 区间;

	uint32 r = 0;
	for (uint32 i = 0; i < num; ++i) {
		区间.push_back({ r, (s[i] - r) });
		r = s[i];
	}


	if (num) {
		区间.push_back({ 开始索引.back(), uint32(me->m_面->m_Mem.m_数量 - 开始索引.back()) });
	}
	else {
		区间.push_back({ 0, uint32(me->m_面->m_Mem.m_数量) });
	}

	
	num = 区间.size();
	f_me_alloc多维材质槽(me, 区间.data(), num, 默认材质);

	if (me->m_元素->m_多维元素数量 != num) {
		if (me->m_元素->m_元素区间) {
			free(me->m_元素->m_元素区间);
		}
		me->m_元素->m_多维元素数量 = num;
		me->m_元素->m_元素区间 = (uvec3*)calloc(me->m_元素->m_多维元素数量, sizeof(uvec3));
	}
	for (uint32 i = 0; i < me->m_元素->m_多维元素数量; ++i) {
		me->m_元素->m_元素区间[i] = _uVec3(区间[i]*3, 区间[i].x);
		me->m_多维材质槽[i].m_区间槽索引 = i;
	}

	
	if (默认材质->m_材质属性.m_Mem.m_数量) {
		S_MeshTranformProp& mt = f_bm_at<S_MeshTranformProp>(me->m_网格元素变换属性);
		mt.m_MaterialID = 默认材质->m_材质属性.m_Mem.m_偏移;
	}
	

}

S_Cube f_me_计算物体包围盒(const S_Bounding& bound, const mat3X3& mat) {
	
	vec3 minCoord = mat * bound.min;
	vec3 maxCoord = mat * bound.max;

	vec3 minNew;
	vec3 maxNew;
	minNew.x = min(minCoord.x, maxCoord.x);
	maxNew.x = max(minCoord.x, maxCoord.x);

	minNew.y = min(minCoord.y, maxCoord.y);
	maxNew.y = max(minCoord.y, maxCoord.y);

	minNew.z = min(minCoord.z, maxCoord.z);
	maxNew.z = max(minCoord.z, maxCoord.z);

	S_Cube cube = S_Cube{ minNew, (maxNew - minNew) * 0.5 };
	cube.pos += cube.size;
	return cube;
}

S_Cube f_me_计算物体包围盒(const S_Bounding& bound, const Mat44f& mat) {
	
	vec3 v[8];
	v[0] = bound.min;
	v[1] = v[0]; v[1].x = bound.max.x;
	v[2] = v[0]; v[2].y = bound.max.y;
	v[3] = v[0]; v[3].z = bound.max.z;

	v[4] = bound.max; v[4].x = bound.min.x;
	v[5] = bound.max; v[5].y = bound.min.y;
	v[6] = bound.max; v[6].z = bound.min.z;
	v[7] = bound.max;


	vec3 minNew = _Vec3(1.0e+8);
	vec3 maxNew = _Vec3(-1.0e+8);
	for (uint32 i = 0; i < 8; ++i) {
		v[i] = mat * v[i];
	}

	for (uint32 i = 0; i < 8; ++i) {
		minNew.x = min(v[i].x, minNew.x);
		maxNew.x = max(v[i].x, maxNew.x);

		minNew.y = min(v[i].y, minNew.y);
		maxNew.y = max(v[i].y, maxNew.y);

		minNew.z = min(v[i].z, minNew.z);
		maxNew.z = max(v[i].z, maxNew.z);
	}

	S_Cube cube = S_Cube{ minNew, (maxNew - minNew) * 0.5 };
	cube.pos += cube.size;
	return cube;
}


void f_mesh_顶点类型切换(S_Mesh* 目标, const S_Mesh* 源) {
	uint32 num = 源->m_顶点->m_Mem.m_数量;

	if (*目标->m_顶点配置Flags  != *源->m_顶点配置Flags) {
		f_mesh_切换顶点类型(目标, *源->m_顶点配置Flags, num);
	}

	*目标->m_顶点配置Flags = *源->m_顶点配置Flags;
	f_bm_copy(*目标->m_顶点, *源->m_顶点);
}



bool f_surface_构建光追底层加速结构(S_Mesh* me, E_物体类型 ObType) {
	if (!me->m_更新光追加速结构 || !me->m_顶点->m_Mem.m_数量 || !me->m_索引->m_Mem.m_数量) return false;
	
	auto* 绘图环境 = f_vk_get绘图环境(me->m_Ctx);
	auto* 绘图框架 = f_vk_get绘图框架(me->m_Ctx);


	me->m_更新光追加速结构 = false;

	std::vector<uint32> 元素数量;
	VkAccelerationStructureGeometryKHR 几何体{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
	几何体.flags = VK_GEOMETRY_OPAQUE_BIT_KHR | VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
	
	

	uint32 图元数量 = 0;
	uint32 最大图元数量 = 0;
	VkAccelerationStructureBuildRangeInfoKHR* 加速体区间绑定 = (VkAccelerationStructureBuildRangeInfoKHR*)malloc(sizeof(VkAccelerationStructureBuildRangeInfoKHR));
	加速体区间绑定->firstVertex = 0;
	加速体区间绑定->primitiveOffset = 0;
	加速体区间绑定->transformOffset = 0;

	switch (ObType) {
		case E_物体类型::t_粒子系统:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			最大图元数量 = me->m_索引->m_Mem.m_数量 / 3;
			assert(最大图元数量 > 1);

			const uint32 元素分割大小 = 0xffffff;
			//if(!me->m_光追图元更新偏移) me->m_光追图元更新偏移 = 100;


			//加速体区间绑定->firstVertex = me->m_光追图元更新偏移 * 3;
			加速体区间绑定->primitiveOffset = me->m_光追图元更新偏移;
			me->m_光追图元更新偏移 += 元素分割大小;

			uint32 分割数量 = 最大图元数量 / 元素分割大小;
			

			if (最大图元数量 >= 元素分割大小 && 最大图元数量 > me->m_光追图元更新偏移) {
				图元数量 = 元素分割大小;

				me->m_更新光追加速结构 = true;
			}
			else {
				图元数量 = 最大图元数量 - (me->m_光追图元更新偏移 - 元素分割大小);
			}
			加速体区间绑定->primitiveCount = 图元数量;
			
			
			

			几何体.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
			几何体.geometry.triangles.vertexStride = sizeof(S_VNT1);
			
			几何体.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
			几何体.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
			几何体.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
			几何体.geometry.triangles.vertexData.deviceAddress = f_buf_getOffsetAddress(*(me->m_顶点));
			几何体.geometry.triangles.indexData.deviceAddress = f_buf_getOffsetAddress(*(me->m_索引));
			几何体.geometry.triangles.maxVertex = me->m_顶点->m_Mem.m_数量;

			break;
		}
		case E_物体类型::t_区域光_方形: {
			加速体区间绑定->primitiveCount = 2;
			最大图元数量 = 2;
			break;
		}
		case E_物体类型::t_区域光_圆形: {
			加速体区间绑定->firstVertex = 4;
			加速体区间绑定->primitiveCount = 128;
			
			最大图元数量 = 128;
			break;
		}
		//case E_物体类型::t_粒子系统: {
		//	//几何体.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
		//	几何体.geometry.aabbs.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR;
		//	几何体.geometry.aabbs.data.deviceAddress = f_buf_getOffsetAddress(*(me->m_顶点));
		//	几何体.geometry.aabbs.stride = sizeof(S_Aabb);
		//	几何体.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR;
		//
		//	
		//	//加速体区间绑定->primitiveCount = me->m_顶点->m_Mem.m_数量 ? 1 : 0;
		//	加速体区间绑定->primitiveCount = me->m_顶点->m_Mem.m_数量;
		//	加速体区间绑定->primitiveOffset = 0;
		//	加速体区间绑定->transformOffset = 0;
		//
		//	图元数量 = me->m_顶点->m_Mem.m_数量;
		//	break;
		//}
		default: return false;
	}



	VkAccelerationStructureBuildGeometryInfoKHR m_加速结构绑定几何信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
	m_加速结构绑定几何信息.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
	m_加速结构绑定几何信息.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
	m_加速结构绑定几何信息.geometryCount = 1;
	//m_加速结构绑定几何信息.geometryCount = 几何体.size();
	m_加速结构绑定几何信息.pGeometries = &几何体;
	//m_加速结构绑定几何信息.pGeometries = 几何体.data();

	VkAccelerationStructureBuildSizesInfoKHR m_加速结构绑定大小信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
	if (!me->m_光追结构更新偏移) {
		绘图框架->vkGetAccelerationStructureBuildSizes(绘图环境->m_设备,
			VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
			&m_加速结构绑定几何信息,
			&最大图元数量,
			&m_加速结构绑定大小信息);

		uint32 size = (m_加速结构绑定大小信息.accelerationStructureSize / 256) + 2;
		size *= 256;

		f_bm_resize(*me->m_底层光追加速结构, size);
	}
	
	
	m_加速结构绑定大小信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
	绘图框架->vkGetAccelerationStructureBuildSizes(绘图环境->m_设备,
		VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
		&m_加速结构绑定几何信息,
		&图元数量,
		&m_加速结构绑定大小信息);
	uint32 临时空间大小 = (m_加速结构绑定大小信息.accelerationStructureSize / 256);
	临时空间大小 *= 256;
	//临时空间大小 = m_加速结构绑定大小信息.accelerationStructureSize;

	S_板载缓存* 暂存缓冲区 = f_buf_create板载缓存(me->m_Ctx, E_板载缓存类型::e_SSBO, E_板载缓存类型::e_SSBO | E_板载缓存类型::e_着色端内存地址, 1, 临时空间大小);


	
	m_加速结构绑定几何信息.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
	m_加速结构绑定几何信息.dstAccelerationStructure = (VkAccelerationStructureKHR)f_buf_get加速结构(*me->m_底层光追加速结构, me->m_光追结构更新偏移, 临时空间大小);
	m_加速结构绑定几何信息.scratchData.deviceAddress = f_buf_getAddress(static_cast<S_VkArray缓存*>(暂存缓冲区));
	


	f_Draw_Begin(&me->m_Ctx, S_光追后端::g_加速结构创建命令缓存, S_光追后端::g_渲染Fence);
	绘图框架->vkCmdBuildAccelerationStructures((VkCommandBuffer)S_光追后端::g_加速结构创建命令缓存, 1, &m_加速结构绑定几何信息, &加速体区间绑定);
	f_Draw_end(&me->m_Ctx, S_光追后端::g_加速结构创建命令缓存, S_光追后端::g_渲染Fence, 3);



	me->m_光追结构更新偏移 += 临时空间大小;

	f_buf_release板载缓存(暂存缓冲区);
	free(加速体区间绑定);

	return true;
}









void f_mesh_save(FILE* f, const S_Mesh* me, uint32 元素位域, Mat44f* mat, bool 压缩) {
	S_文件块 文件块 = f_文件块_创建(E_引擎文件块类型::e_引擎文件块_网格, 0);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_文件块_写数据块(块, 元素位域);
	f_文件块_写数据块(块, 压缩);

	if (元素位域 & uint32(E_网格缓存元素位域::e_顶点坐标)) {
		f_文件块_写数据块(块, *me->m_顶点配置Flags);

		std::vector<S_VNT1> vert;
		if (mat) {
			vert = f_mesh_顶点变换(*me, *mat);
		}
		else {
			vert = f_mesh_STL_顶点(*me);
		}
		f_文件块_写序列数据块(块, vert, 压缩);
	}
	if (元素位域 & uint32(E_网格缓存元素位域::e_顶点索引)) {
		auto 索引 = f_mesh_STL_索引(*me);
		f_文件块_写序列数据块(块, 索引, 压缩);
	}
	if (元素位域 & uint32(E_网格缓存元素位域::e_顶点颜色)) {
		f_文件块_写内存块(块, *me->m_颜色);
	}
	if (元素位域 & uint32(E_网格缓存元素位域::e_顶点权重)) {
		
	}
	if (元素位域 & uint32(E_网格缓存元素位域::e_面材质ID)) {
		
	}

	f_file_保存文件块(f, 文件块, 块);
}

void f_mesh_load(FILE* f, S_Mesh* me, uint32 元素位域) {
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_引擎文件块类型::e_引擎文件块_网格) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		uint32 读取元素位域 = 0;
		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 读取元素位域);
		bool 解压缩 = false;
		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 解压缩);

		if ((读取元素位域 & uint32(E_网格缓存元素位域::e_顶点坐标) & 元素位域)) {
			uint32 顶点配置 = 0;
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 顶点配置);

			switch (顶点配置) {
				case E_顶点组合标志::e_坐标_法线_UV: {
					std::vector<S_VNT1> vert;
					下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, vert, 解压缩);
					f_mesh_fill顶点数据(me, vert);
					break;
				}
				default:
					break;
			}
		}
		if ((读取元素位域 & uint32(E_网格缓存元素位域::e_顶点索引) & 元素位域)) {
			下一次读取数据指针 = f_文件块_读内存块(下一次读取数据指针, *me->m_索引);
		}

		f_mesh_计算包围盒(me);
	}
	free(文件块.m_data);
}

void f_mesh_load(const std::vector<std::filesystem::path>& path, S_Mesh* me, uint32 元素位域) {
	std::vector<S_VNT1> 顶点;
	std::vector<uint32> 索引;
	std::vector<S_FaceElement> 面属性;

	uint32 offset = 0;
	int32 元素ID = 0;
	for (auto& e : path) {
		FILE* f = fopen(e.generic_string().c_str(), "rb");
		if (f) {
			
			S_文件块 文件块 = f_file_读取文件块(f);
			if (文件块.m_块类型 == E_引擎文件块类型::e_引擎文件块_网格) {
				const uint8* 下一次读取数据指针 = 文件块.m_data;

				uint32 读取元素位域 = 0;
				下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 读取元素位域);
				bool 解压缩 = false;
				下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 解压缩);

				if ((读取元素位域 & uint32(E_网格缓存元素位域::e_顶点坐标) & 元素位域)) {
					uint32 顶点配置 = 0;
					下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 顶点配置);

					switch (顶点配置) {
						case E_顶点组合标志::e_坐标_法线_UV: {
							offset += 顶点.size();

							std::vector<S_VNT1> vert;
							下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, vert, 解压缩);
							顶点.insert(顶点.end(), vert.begin(), vert.end());
							
							break;
						}
						default:
							break;
					}
				}
				if (读取元素位域 & uint32(E_网格缓存元素位域::e_顶点索引)) {
					
					std::vector<uint32> index;
					下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, index, 解压缩);

					if (读取元素位域 & 元素位域) {
						std::vector<S_FaceElement> face(index.size() / 3, { 元素ID, 元素ID,0,0,0xffffffff});

						index += offset;
						索引.insert(索引.end(), index.begin(), index.end());
						面属性.insert(面属性.end(), face.begin(), face.end());
					}
					//下一次读取数据指针 = f_文件块_读内存块(下一次读取数据指针, *me->m_索引);
				}
				++元素ID;
			}
			free(文件块.m_data);

			fclose(f);
		}
	}

	f_mesh_fill顶点数据(me, 顶点);
	f_me_fill索引(me, 索引);
	f_mesh_fill面(me, 面属性);

	f_mesh_计算包围盒(me);
}



void f_me_render(S_网格包& 包, S_材质管线* 线管, const E_管线槽 管线槽, float32 深度偏移) {
	auto& me = *包.m_Mesh;
	auto* rt = f_vk_get绘图环境(me.m_Ctx);

	assert(me.m_绘制类型 < S_元素绘制类型::e_绘制类型_结束);
	
	switch (管线槽) {
		case E_管线槽::e_颜色渲染: {
			线管->m_着色线管->m_Pipeline->f_bind(包.m_常量推送);
			break;
		}
		case E_管线槽::e_几何渲染: {
			线管->m_几何着色线管->m_Pipeline->f_bind(包.m_常量推送);
			break;
		}
		case E_管线槽::e_环境渲染: {
			线管->m_环境着色线管->m_Pipeline->f_bind(包.m_常量推送);
			break;
		}
		case E_管线槽::e_阴影渲染: {
			线管->m_阴影着色线管->m_Pipeline->f_bind(包.m_常量推送);
			break;
		}
		default:
			break;
	}
	vkCmdSetLineWidth(rt->m_命令缓存, me.m_线宽);
	vkCmdSetDepthBias(rt->m_命令缓存, -深度偏移, 0, 0);

	switch (me.m_绘制类型) {
		case S_元素绘制类型::e_绘制类型_序列: {
			auto& m = *me.m_顶点;
			vkCmdDraw(rt->m_命令缓存, m.m_Mem.m_数量, 1, m.m_Mem.m_偏移, 0);
			break;
		}
		case S_元素绘制类型::e_绘制类型_索引: {
			auto& m = *me.m_顶点;
			vkCmdDrawIndexed(rt->m_命令缓存, me.m_索引->m_Mem.m_数量, 1, me.m_索引->m_Mem.m_偏移, m.m_Mem.m_偏移, 0);
			break;
		}
		case S_元素绘制类型::e_绘制类型_无顶点索引: {
			vkCmdDraw(rt->m_命令缓存, me.m_顶点数量, 1, 0, 0);
			break;
		}
		case S_元素绘制类型::e_绘制类型_间接: {
			auto& m = *me.m_间接;
			vkCmdDrawIndirect(rt->m_命令缓存, 
							  f_vk_get缓存对象(m), 
							  m.m_Mem.m_偏移 * sizeof(S_VkDrawIndirectCommand), 
							  m.m_Mem.m_数量,
							  sizeof(S_VkDrawIndirectCommand));
			break;
		}
		case S_元素绘制类型::e_绘制类型_间接索引: {
			auto& m = *me.m_间接;
			vkCmdDrawIndexedIndirect(rt->m_命令缓存, 
									f_vk_get缓存对象(m), 
									m.m_Mem.m_偏移 * sizeof(S_VkDrawIndexedIndirectCommand), 
									m.m_Mem.m_数量,
									sizeof(S_VkDrawIndexedIndirectCommand));
			break;
		}
		default:
			break;
	}
}








//Inline void f_计算线段拾取坐标(S_Mesh* mesh, S_线拾取& 拾取线) {
//	vec3 v1, v2 = { };
//	switch (*mesh->m_顶点配置Flags) {
//		case E_顶点组合标志::e_坐标_法线_UV: {
//			//auto* v = f_buf_VNT_ptr(*mesh->m_顶点);
//			auto* v = (S_VNT1*)顶点指针;
//			uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
//			v1 = v[index].vert;
//			v2 = v[index + 1].vert;
//			break;
//		}
//		case E_顶点组合标志::e_坐标_法线: {
//			//S_VN* vn= f_buf_VN_ptr(*mesh->m_顶点);
//			auto* v = (S_VN*)顶点指针;
//			uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
//			v1 = v[index].vert;
//			v2 = v[index + 1].vert;
//			break;
//		}
//		case E_顶点组合标志::e_坐标_颜色: {
//			//S_VC* v = f_buf_VC_ptr(*mesh->m_顶点);
//			auto* v = (S_VC*)顶点指针;
//			uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
//			v1 = v[index].vert;
//			v2 = v[index + 1].vert;
//			break;
//		}
//		default: {
//			//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
//			auto* v = (vec3*)顶点指针;
//			uint32 index = 拾取线.线索引 * 2 + Offset_num.x;
//			v1 = v[index];
//			v2 = v[index + 1];
//			break;
//		}
//	}
//	vec3 p1 = mat[0] * v1;
//	vec3 p2 = mat[0] * v1;
//
//	拾取线.交点 = (p2 - p1) * 交点 + p1;
//}







